summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuilhem Lavaux <guilhem@kaffe.org>2006-08-14 09:40:47 +0000
committerGuilhem Lavaux <guilhem@kaffe.org>2006-08-14 09:40:47 +0000
commit310be467f8f83b189b4a40faece32478fad67bc9 (patch)
tree777d0c539432a12c86f450e8d3bf90e8e5677f57
parent8f2887fc8c74aae0d541cbd59ea36c37d420267d (diff)
downloadclasspath-310be467f8f83b189b4a40faece32478fad67bc9.tar.gz
2006-08-14 Guilhem Lavaux <guilhem@kaffe.org>
* Merged HEAD as of 2006-08-14 0:00.
-rw-r--r--.classpath2
-rw-r--r--ChangeLog3936
-rw-r--r--ChangeLog.native6
-rw-r--r--INSTALL39
-rw-r--r--NEWS28
-rw-r--r--README56
-rwxr-xr-xautogen.sh5
-rw-r--r--configure.ac81
-rw-r--r--doc/vmintegration.texinfo57
-rw-r--r--doc/www.gnu.org/announce/20060809.wml225
-rw-r--r--doc/www.gnu.org/downloads/downloads.wml14
-rw-r--r--doc/www.gnu.org/newsitems.txt5
-rw-r--r--examples/.cvsignore2
-rw-r--r--examples/Makefile.am11
-rw-r--r--examples/Makefile.java2d.in17
-rw-r--r--examples/README17
-rw-r--r--examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/StructureToPassHelper.java15
-rw-r--r--examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/StructureToReturnHelper.java25
-rw-r--r--examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/TreeNodeHelper.java11
-rw-r--r--examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/WeThrowThisExceptionHelper.java6
-rw-r--r--examples/gnu/classpath/examples/awt/Demo.java201
-rw-r--r--examples/gnu/classpath/examples/java2d/bench.c606
-rw-r--r--examples/gnu/classpath/examples/java2d/bench.h64
-rw-r--r--examples/gnu/classpath/examples/management/TestBeans.java55
-rw-r--r--examples/gnu/classpath/examples/swing/Demo.java40
-rw-r--r--examples/gnu/classpath/examples/swing/HtmlDemo.java133
-rw-r--r--gnu/CORBA/Connected_objects.java10
-rw-r--r--gnu/CORBA/ForwardRequestHelper.java25
-rw-r--r--gnu/CORBA/OrbFunctional.java10
-rw-r--r--gnu/classpath/debug/Simple1LineFormatter.java7
-rw-r--r--gnu/classpath/debug/SystemLogger.java8
-rw-r--r--gnu/classpath/jdwp/event/ExceptionEvent.java27
-rw-r--r--gnu/classpath/jdwp/util/Location.java40
-rw-r--r--gnu/java/awt/ClasspathToolkit.java22
-rw-r--r--gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java114
-rw-r--r--gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java121
-rw-r--r--gnu/java/awt/dnd/peer/gtk/GtkDropTargetContextPeer.java10
-rw-r--r--gnu/java/awt/java2d/CubicSegment.java98
-rw-r--r--gnu/java/awt/java2d/LineSegment.java21
-rw-r--r--gnu/java/awt/java2d/QuadSegment.java24
-rw-r--r--gnu/java/awt/java2d/Segment.java37
-rw-r--r--gnu/java/awt/peer/ClasspathFontPeer.java7
-rw-r--r--gnu/java/awt/peer/GLightweightPeer.java221
-rw-r--r--gnu/java/awt/peer/gtk/BufferedImageGraphics.java11
-rw-r--r--gnu/java/awt/peer/gtk/CairoGraphics2D.java152
-rw-r--r--gnu/java/awt/peer/gtk/CairoSurface.java123
-rw-r--r--gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java5
-rw-r--r--gnu/java/awt/peer/gtk/ComponentGraphics.java83
-rw-r--r--gnu/java/awt/peer/gtk/ComponentGraphicsCopy.java6
-rw-r--r--gnu/java/awt/peer/gtk/GdkFontPeer.java3
-rw-r--r--gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java14
-rw-r--r--gnu/java/awt/peer/gtk/GdkPixbufDecoder.java3
-rw-r--r--gnu/java/awt/peer/gtk/GtkButtonPeer.java5
-rw-r--r--gnu/java/awt/peer/gtk/GtkCanvasPeer.java4
-rw-r--r--gnu/java/awt/peer/gtk/GtkCheckboxPeer.java3
-rw-r--r--gnu/java/awt/peer/gtk/GtkChoicePeer.java101
-rw-r--r--gnu/java/awt/peer/gtk/GtkClipboardNotifier.java4
-rw-r--r--gnu/java/awt/peer/gtk/GtkComponentPeer.java89
-rw-r--r--gnu/java/awt/peer/gtk/GtkContainerPeer.java3
-rw-r--r--gnu/java/awt/peer/gtk/GtkDialogPeer.java5
-rw-r--r--gnu/java/awt/peer/gtk/GtkFramePeer.java8
-rw-r--r--gnu/java/awt/peer/gtk/GtkImage.java2
-rw-r--r--gnu/java/awt/peer/gtk/GtkImageConsumer.java7
-rw-r--r--gnu/java/awt/peer/gtk/GtkMainThread.java97
-rw-r--r--gnu/java/awt/peer/gtk/GtkMenuBarPeer.java3
-rw-r--r--gnu/java/awt/peer/gtk/GtkMenuItemPeer.java5
-rw-r--r--gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java76
-rw-r--r--gnu/java/awt/peer/gtk/GtkPanelPeer.java3
-rw-r--r--gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java1
-rw-r--r--gnu/java/awt/peer/gtk/GtkScrollbarPeer.java2
-rw-r--r--gnu/java/awt/peer/gtk/GtkToolkit.java49
-rw-r--r--gnu/java/awt/peer/gtk/GtkWindowPeer.java54
-rw-r--r--gnu/java/awt/peer/gtk/VolatileImageGraphics.java14
-rw-r--r--gnu/java/awt/peer/qt/QtCheckboxPeer.java3
-rw-r--r--gnu/java/awt/peer/qt/QtComponentGraphics.java4
-rw-r--r--gnu/java/awt/peer/qt/QtComponentPeer.java3
-rw-r--r--gnu/java/awt/peer/qt/QtContainerPeer.java3
-rw-r--r--gnu/java/awt/peer/qt/QtDialogPeer.java4
-rw-r--r--gnu/java/awt/peer/qt/QtEmbeddedWindowPeer.java3
-rw-r--r--gnu/java/awt/peer/qt/QtFontMetrics.java5
-rw-r--r--gnu/java/awt/peer/qt/QtFontPeer.java3
-rw-r--r--gnu/java/awt/peer/qt/QtGraphics.java3
-rw-r--r--gnu/java/awt/peer/qt/QtGraphicsEnvironment.java3
-rw-r--r--gnu/java/awt/peer/qt/QtImage.java3
-rw-r--r--gnu/java/awt/peer/qt/QtImageConsumer.java7
-rw-r--r--gnu/java/awt/peer/qt/QtImageDirectGraphics.java21
-rw-r--r--gnu/java/awt/peer/qt/QtImageGraphics.java4
-rw-r--r--gnu/java/awt/peer/qt/QtMenuBarPeer.java3
-rw-r--r--gnu/java/awt/peer/qt/QtMenuItemPeer.java3
-rw-r--r--gnu/java/awt/peer/qt/QtPopupMenuPeer.java5
-rw-r--r--gnu/java/awt/peer/qt/QtScreenDeviceConfiguration.java4
-rw-r--r--gnu/java/awt/peer/qt/QtScrollPanePeer.java3
-rw-r--r--gnu/java/awt/peer/qt/QtToolkit.java23
-rw-r--r--gnu/java/awt/peer/qt/QtVolatileImage.java6
-rw-r--r--gnu/java/awt/peer/x/XDialogPeer.java (renamed from gnu/java/awt/dnd/peer/gtk/GtkDropTargetPeer.java)25
-rw-r--r--gnu/java/awt/peer/x/XEventPump.java4
-rw-r--r--gnu/java/awt/peer/x/XFontPeer.java28
-rw-r--r--gnu/java/awt/peer/x/XFramePeer.java249
-rw-r--r--gnu/java/awt/peer/x/XGraphics.java489
-rw-r--r--gnu/java/awt/peer/x/XGraphicsEnvironment.java2
-rw-r--r--gnu/java/awt/peer/x/XImage.java14
-rw-r--r--gnu/java/awt/peer/x/XToolkit.java87
-rw-r--r--gnu/java/awt/peer/x/XWindowPeer.java1
-rw-r--r--gnu/java/awt/peer/x/fonts.properties25
-rw-r--r--gnu/java/lang/management/BeanImpl.java461
-rw-r--r--gnu/java/lang/management/ClassLoadingMXBeanImpl.java16
-rw-r--r--gnu/java/lang/management/CompilationMXBeanImpl.java16
-rw-r--r--gnu/java/lang/management/GarbageCollectorMXBeanImpl.java9
-rw-r--r--gnu/java/lang/management/MemoryMXBeanImpl.java236
-rw-r--r--gnu/java/lang/management/MemoryManagerMXBeanImpl.java25
-rw-r--r--gnu/java/lang/management/MemoryPoolMXBeanImpl.java13
-rw-r--r--gnu/java/lang/management/OperatingSystemMXBeanImpl.java18
-rw-r--r--gnu/java/lang/management/RuntimeMXBeanImpl.java16
-rw-r--r--gnu/java/lang/management/ThreadMXBeanImpl.java9
-rw-r--r--gnu/java/net/local/LocalSocketImpl.java19
-rw-r--r--gnu/java/net/protocol/http/Request.java15
-rw-r--r--gnu/java/nio/SelectionKeyImpl.java22
-rw-r--r--gnu/java/nio/SelectorImpl.java7
-rw-r--r--gnu/java/rmi/server/ActivatableServerRef.java2
-rw-r--r--gnu/java/rmi/server/UnicastServerRef.java2
-rw-r--r--gnu/java/security/Engine.java212
-rw-r--r--gnu/java/security/OID.java24
-rw-r--r--gnu/java/security/PolicyFile.java19
-rw-r--r--gnu/java/security/Registry.java12
-rw-r--r--gnu/java/security/key/dss/DSSKey.java45
-rw-r--r--gnu/java/security/key/dss/DSSKeyPairX509Codec.java92
-rw-r--r--gnu/java/security/key/dss/DSSPrivateKey.java6
-rw-r--r--gnu/java/security/key/dss/DSSPublicKey.java6
-rw-r--r--gnu/java/security/key/rsa/GnuRSAKey.java6
-rw-r--r--gnu/java/security/key/rsa/GnuRSAPrivateKey.java6
-rw-r--r--gnu/java/security/key/rsa/GnuRSAPublicKey.java6
-rw-r--r--gnu/java/security/key/rsa/RSAKeyPairPKCS8Codec.java11
-rw-r--r--gnu/java/security/util/ByteArray.java (renamed from gnu/classpath/ByteArray.java)2
-rw-r--r--gnu/java/security/util/IntegerUtil.java109
-rw-r--r--gnu/java/util/prefs/GConfBasedPreferences.java14
-rw-r--r--gnu/java/util/prefs/gconf/GConfNativePeer.java114
-rw-r--r--gnu/java/util/regex/RE.java32
-rw-r--r--gnu/java/util/regex/RETokenEnd.java20
-rw-r--r--gnu/java/util/regex/RETokenStart.java23
-rw-r--r--gnu/javax/crypto/RSACipherImpl.java2
-rw-r--r--gnu/javax/crypto/cipher/DES.java2
-rw-r--r--gnu/javax/crypto/cipher/TripleDES.java132
-rw-r--r--gnu/javax/crypto/jce/GnuCrypto.java10
-rw-r--r--gnu/javax/crypto/jce/cipher/AES128KeyWrapSpi.java54
-rw-r--r--gnu/javax/crypto/jce/cipher/AES192KeyWrapSpi.java54
-rw-r--r--gnu/javax/crypto/jce/cipher/AES256KeyWrapSpi.java54
-rw-r--r--gnu/javax/crypto/jce/cipher/AESKeyWrapSpi.java88
-rw-r--r--gnu/javax/crypto/jce/cipher/CipherAdapter.java6
-rw-r--r--gnu/javax/crypto/jce/cipher/KeyWrappingAlgorithmAdapter.java423
-rw-r--r--gnu/javax/crypto/jce/cipher/TripleDESKeyWrapSpi.java54
-rw-r--r--gnu/javax/crypto/jce/params/BlockCipherParameters.java7
-rw-r--r--gnu/javax/crypto/key/dh/GnuDHKey.java6
-rw-r--r--gnu/javax/crypto/key/dh/GnuDHPrivateKey.java6
-rw-r--r--gnu/javax/crypto/key/dh/GnuDHPublicKey.java6
-rw-r--r--gnu/javax/crypto/kwa/AESKeyWrap.java168
-rw-r--r--gnu/javax/crypto/kwa/BaseKeyWrappingAlgorithm.java145
-rw-r--r--gnu/javax/crypto/kwa/IKeyWrappingAlgorithm.java160
-rw-r--r--gnu/javax/crypto/kwa/KeyUnwrappingException.java67
-rw-r--r--gnu/javax/crypto/kwa/KeyWrappingAlgorithmFactory.java110
-rw-r--r--gnu/javax/crypto/kwa/TripleDESKeyWrap.java292
-rw-r--r--gnu/javax/crypto/pad/BasePad.java23
-rw-r--r--gnu/javax/crypto/pad/IPad.java24
-rw-r--r--gnu/javax/crypto/sasl/plain/PasswordFile.java8
-rw-r--r--gnu/javax/imageio/IIOInputStream.java (renamed from gnu/javax/imageio/gif/GIFStream.java)10
-rw-r--r--gnu/javax/imageio/gif/GIFImageReader.java7
-rw-r--r--gnu/javax/imageio/gif/GIFImageReaderSpi.java4
-rw-r--r--gnu/javax/imageio/png/PNGChunk.java284
-rw-r--r--gnu/javax/imageio/png/PNGData.java104
-rw-r--r--gnu/javax/imageio/png/PNGDecoder.java331
-rw-r--r--gnu/javax/imageio/png/PNGEncoder.java235
-rw-r--r--gnu/javax/imageio/png/PNGException.java48
-rw-r--r--gnu/javax/imageio/png/PNGFile.java258
-rw-r--r--gnu/javax/imageio/png/PNGFilter.java237
-rw-r--r--gnu/javax/imageio/png/PNGGamma.java89
-rw-r--r--gnu/javax/imageio/png/PNGHeader.java257
-rw-r--r--gnu/javax/imageio/png/PNGICCProfile.java114
-rw-r--r--gnu/javax/imageio/png/PNGImageReader.java224
-rw-r--r--gnu/javax/imageio/png/PNGImageReaderSpi.java128
-rw-r--r--gnu/javax/imageio/png/PNGPalette.java127
-rw-r--r--gnu/javax/imageio/png/PNGPhys.java112
-rw-r--r--gnu/javax/imageio/png/PNGTime.java83
-rw-r--r--gnu/javax/naming/giop/ContextContinuation.java956
-rw-r--r--gnu/javax/naming/giop/CorbalocParser.java439
-rw-r--r--gnu/javax/naming/giop/GiopNamingEnumeration.java187
-rw-r--r--gnu/javax/naming/giop/GiopNamingServiceFactory.java177
-rw-r--r--gnu/javax/naming/giop/GiopNamingServiceURLContext.java840
-rw-r--r--gnu/javax/naming/giop/ListBindingsEnumeration.java116
-rw-r--r--gnu/javax/naming/giop/ListEnumeration.java116
-rw-r--r--gnu/javax/naming/ictxImpl/trans/GnuName.java467
-rw-r--r--gnu/javax/naming/jndi/url/corbaname/corbanameURLContextFactory.java53
-rw-r--r--gnu/javax/naming/jndi/url/rmi/ContextContinuation.java597
-rw-r--r--gnu/javax/naming/jndi/url/rmi/ListBindingsEnumeration.java97
-rw-r--r--gnu/javax/naming/jndi/url/rmi/ListEnumeration.java80
-rw-r--r--gnu/javax/naming/jndi/url/rmi/RmiContinuation.java594
-rw-r--r--gnu/javax/naming/jndi/url/rmi/RmiNamingEnumeration.java130
-rw-r--r--gnu/javax/naming/jndi/url/rmi/rmiURLContext.java637
-rw-r--r--gnu/javax/naming/jndi/url/rmi/rmiURLContextFactory.java66
-rw-r--r--gnu/javax/print/ipp/IppRequest.java4
-rw-r--r--gnu/javax/security/auth/callback/AbstractCallbackHandler.java97
-rw-r--r--gnu/javax/sound/sampled/AU/AUReader.java212
-rw-r--r--gnu/javax/sound/sampled/WAV/WAVReader.java236
-rw-r--r--gnu/javax/swing/text/html/parser/GnuParserDelegator.java178
-rw-r--r--gnu/javax/swing/text/html/parser/HTML_401F.java47
-rw-r--r--gnu/javax/swing/text/html/parser/HTML_401Swing.java91
-rw-r--r--gnu/javax/swing/text/html/parser/htmlValidator.java39
-rw-r--r--gnu/xml/dom/DomIterator.java8
-rw-r--r--gnu/xml/transform/ApplyTemplatesNode.java2
-rw-r--r--gnu/xml/transform/ForEachNode.java2
-rw-r--r--include/GtkDragSourceContextPeer.h23
-rw-r--r--include/Makefile.am4
-rw-r--r--include/gnu_java_awt_peer_gtk_CairoGraphics2D.h4
-rw-r--r--include/gnu_java_awt_peer_gtk_ComponentGraphics.h1
-rw-r--r--include/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h1
-rw-r--r--include/gnu_java_awt_peer_gtk_GdkTextLayout.h27
-rw-r--r--include/gnu_java_awt_peer_gtk_GtkChoicePeer.h3
-rw-r--r--include/gnu_java_awt_peer_gtk_GtkComponentPeer.h2
-rw-r--r--include/gnu_java_awt_peer_gtk_GtkToolkit.h2
-rw-r--r--include/gnu_java_awt_peer_gtk_GtkWindowPeer.h2
-rw-r--r--include/gnu_java_net_local_LocalSocketImpl.h6
-rw-r--r--include/java_lang_VMSystem.h2
-rw-r--r--include/jvmti.h1815
-rw-r--r--java/awt/AWTEvent.java5
-rw-r--r--java/awt/BasicStroke.java275
-rw-r--r--java/awt/Canvas.java4
-rw-r--r--java/awt/CardLayout.java19
-rw-r--r--java/awt/CheckboxMenuItem.java20
-rw-r--r--java/awt/Choice.java727
-rw-r--r--java/awt/Component.java1173
-rw-r--r--java/awt/Container.java394
-rw-r--r--java/awt/ContainerOrderFocusTraversalPolicy.java36
-rw-r--r--java/awt/Cursor.java15
-rw-r--r--java/awt/DefaultKeyboardFocusManager.java140
-rw-r--r--java/awt/EventDispatchThread.java12
-rw-r--r--java/awt/FlowLayout.java10
-rw-r--r--java/awt/Font.java30
-rw-r--r--java/awt/Graphics2D.java12
-rw-r--r--java/awt/GridBagLayout.java121
-rw-r--r--java/awt/GridLayout.java12
-rw-r--r--java/awt/Image.java38
-rw-r--r--java/awt/KeyboardFocusManager.java92
-rw-r--r--java/awt/LightweightDispatcher.java38
-rw-r--r--java/awt/List.java120
-rw-r--r--java/awt/Menu.java20
-rw-r--r--java/awt/MenuBar.java22
-rw-r--r--java/awt/MenuComponent.java14
-rw-r--r--java/awt/MenuItem.java25
-rw-r--r--java/awt/MouseInfo.java95
-rw-r--r--java/awt/PointerInfo.java84
-rw-r--r--java/awt/PopupMenu.java24
-rw-r--r--java/awt/ScrollPane.java32
-rw-r--r--java/awt/TextField.java21
-rw-r--r--java/awt/Toolkit.java22
-rw-r--r--java/awt/Window.java128
-rw-r--r--java/awt/dnd/DragGestureRecognizer.java1
-rw-r--r--java/awt/dnd/DragSource.java32
-rw-r--r--java/awt/dnd/DropTarget.java36
-rw-r--r--java/awt/dnd/DropTargetDragEvent.java14
-rw-r--r--java/awt/font/FontRenderContext.java8
-rw-r--r--java/awt/font/TextLayout.java3
-rw-r--r--java/awt/font/TextMeasurer.java2
-rw-r--r--java/awt/geom/AffineTransform.java16
-rw-r--r--java/awt/geom/GeneralPath.java4
-rw-r--r--java/awt/image/BandedSampleModel.java342
-rw-r--r--java/awt/image/BufferedImage.java365
-rw-r--r--java/awt/image/BufferedImageOp.java58
-rw-r--r--java/awt/image/ByteLookupTable.java17
-rw-r--r--java/awt/image/ColorConvertOp.java15
-rw-r--r--java/awt/image/ColorModel.java29
-rw-r--r--java/awt/image/ComponentSampleModel.java13
-rw-r--r--java/awt/image/ConvolveOp.java178
-rw-r--r--java/awt/image/DataBuffer.java23
-rw-r--r--java/awt/image/Kernel.java62
-rw-r--r--java/awt/image/MultiPixelPackedSampleModel.java458
-rw-r--r--java/awt/image/Raster.java780
-rw-r--r--java/awt/image/RasterOp.java50
-rw-r--r--java/awt/image/SampleModel.java461
-rw-r--r--java/awt/image/ShortLookupTable.java39
-rw-r--r--java/awt/image/SinglePixelPackedSampleModel.java307
-rw-r--r--java/awt/image/WritableRaster.java346
-rw-r--r--java/awt/peer/ComponentPeer.java33
-rw-r--r--java/awt/peer/MouseInfoPeer.java61
-rw-r--r--java/awt/peer/WindowPeer.java5
-rw-r--r--java/io/ObjectInputStream.java9
-rw-r--r--java/io/ObjectStreamField.java24
-rw-r--r--java/io/PrintStream.java76
-rw-r--r--java/lang/Iterable.java3
-rw-r--r--java/lang/StrictMath.java652
-rw-r--r--java/lang/management/ManagementFactory.java104
-rw-r--r--java/lang/management/MemoryMXBean.java28
-rw-r--r--java/lang/management/MemoryNotificationInfo.java215
-rw-r--r--java/lang/management/MemoryPoolMXBean.java8
-rw-r--r--java/lang/management/MemoryUsage.java45
-rw-r--r--java/lang/management/ThreadInfo.java271
-rw-r--r--java/math/BigDecimal.java128
-rw-r--r--java/math/BigInteger.java60
-rw-r--r--java/net/Inet6Address.java171
-rw-r--r--java/net/URL.java3
-rw-r--r--java/net/URLStreamHandler.java21
-rw-r--r--java/nio/DirectByteBufferImpl.java3
-rw-r--r--java/nio/channels/SelectionKey.java6
-rw-r--r--java/nio/channels/spi/AbstractSelectionKey.java6
-rw-r--r--java/security/AccessControlContext.java22
-rw-r--r--java/security/AlgorithmParameterGenerator.java100
-rw-r--r--java/security/AlgorithmParameters.java122
-rw-r--r--java/security/KeyFactory.java99
-rw-r--r--java/security/KeyPairGenerator.java91
-rw-r--r--java/security/KeyStore.java132
-rw-r--r--java/security/MessageDigest.java109
-rw-r--r--java/security/Provider.java92
-rw-r--r--java/security/SecureRandom.java135
-rw-r--r--java/security/Signature.java105
-rw-r--r--java/security/cert/CertPathBuilder.java113
-rw-r--r--java/security/cert/CertPathValidator.java103
-rw-r--r--java/security/cert/CertStore.java115
-rw-r--r--java/security/cert/CertificateFactory.java126
-rw-r--r--java/text/SimpleDateFormat.java20
-rw-r--r--java/util/Arrays.java6
-rw-r--r--java/util/GregorianCalendar.java4
-rw-r--r--java/util/Locale.java48
-rw-r--r--java/util/ResourceBundle.java134
-rw-r--r--java/util/UUID.java383
-rw-r--r--java/util/Vector.java6
-rw-r--r--java/util/regex/Pattern.java8
-rw-r--r--java/util/zip/ZipFile.java30
-rw-r--r--javax/crypto/Cipher.java207
-rw-r--r--javax/crypto/ExemptionMechanism.java117
-rw-r--r--javax/crypto/KeyAgreement.java116
-rw-r--r--javax/crypto/KeyGenerator.java114
-rw-r--r--javax/crypto/Mac.java118
-rw-r--r--javax/crypto/SecretKeyFactory.java108
-rw-r--r--javax/crypto/spec/SecretKeySpec.java18
-rw-r--r--javax/imageio/spi/IIORegistry.java4
-rw-r--r--javax/management/BadAttributeValueExpException.java91
-rw-r--r--javax/management/BadStringOperationException.java92
-rw-r--r--javax/management/InstanceAlreadyExistsException.java76
-rw-r--r--javax/management/InstanceNotFoundException.java76
-rw-r--r--javax/management/IntrospectionException.java78
-rw-r--r--javax/management/InvalidApplicationException.java92
-rw-r--r--javax/management/ListenerNotFoundException.java75
-rw-r--r--javax/management/MBeanAttributeInfo.java301
-rw-r--r--javax/management/MBeanConstructorInfo.java232
-rw-r--r--javax/management/MBeanFeatureInfo.java38
-rw-r--r--javax/management/MBeanInfo.java258
-rw-r--r--javax/management/MBeanNotificationInfo.java227
-rw-r--r--javax/management/MBeanOperationInfo.java348
-rw-r--r--javax/management/MBeanParameterInfo.java176
-rw-r--r--javax/management/MBeanRegistrationException.java84
-rw-r--r--javax/management/MalformedObjectNameException.java76
-rw-r--r--javax/management/NotCompliantMBeanException.java78
-rw-r--r--javax/management/Notification.java314
-rw-r--r--javax/management/NotificationBroadcaster.java112
-rw-r--r--javax/management/NotificationEmitter.java76
-rw-r--r--javax/management/NotificationFilter.java66
-rw-r--r--javax/management/NotificationListener.java70
-rw-r--r--javax/management/OperationsException.java5
-rw-r--r--javax/management/RuntimeErrorException.java115
-rw-r--r--javax/management/RuntimeMBeanException.java114
-rw-r--r--javax/management/ServiceNotFoundException.java75
-rw-r--r--javax/management/StandardMBean.java921
-rw-r--r--javax/management/openmbean/ArrayType.java313
-rw-r--r--javax/management/openmbean/CompositeData.java154
-rw-r--r--javax/management/openmbean/CompositeDataSupport.java349
-rw-r--r--javax/management/openmbean/CompositeType.java324
-rw-r--r--javax/management/openmbean/InvalidKeyException.java77
-rw-r--r--javax/management/openmbean/InvalidOpenTypeException.java76
-rw-r--r--javax/management/openmbean/KeyAlreadyExistsException.java77
-rw-r--r--javax/management/openmbean/OpenDataException.java79
-rw-r--r--javax/management/openmbean/OpenMBeanAttributeInfo.java120
-rw-r--r--javax/management/openmbean/OpenMBeanAttributeInfoSupport.java546
-rw-r--r--javax/management/openmbean/OpenMBeanConstructorInfo.java112
-rw-r--r--javax/management/openmbean/OpenMBeanConstructorInfoSupport.java174
-rw-r--r--javax/management/openmbean/OpenMBeanInfo.java154
-rw-r--r--javax/management/openmbean/OpenMBeanInfoSupport.java191
-rw-r--r--javax/management/openmbean/OpenMBeanOperationInfo.java154
-rw-r--r--javax/management/openmbean/OpenMBeanOperationInfoSupport.java240
-rw-r--r--javax/management/openmbean/OpenMBeanParameterInfo.java190
-rw-r--r--javax/management/openmbean/OpenMBeanParameterInfoSupport.java511
-rw-r--r--javax/management/openmbean/OpenType.java230
-rw-r--r--javax/management/openmbean/SimpleType.java342
-rw-r--r--javax/management/openmbean/TabularData.java259
-rw-r--r--javax/management/openmbean/TabularDataSupport.java652
-rw-r--r--javax/management/openmbean/TabularType.java269
-rw-r--r--javax/management/openmbean/package.html64
-rw-r--r--javax/naming/Name.java14
-rw-r--r--javax/naming/spi/NamingManager.java32
-rw-r--r--javax/net/ssl/KeyManagerFactory.java106
-rw-r--r--javax/net/ssl/SSLContext.java125
-rw-r--r--javax/net/ssl/TrustManagerFactory.java103
-rw-r--r--javax/rmi/ssl/SslRMIClientSocketFactory.java166
-rw-r--r--javax/rmi/ssl/SslRMIServerSocketFactory.java213
-rw-r--r--javax/security/auth/login/LoginContext.java8
-rw-r--r--javax/swing/AbstractButton.java19
-rw-r--r--javax/swing/ButtonGroup.java53
-rw-r--r--javax/swing/DefaultBoundedRangeModel.java34
-rw-r--r--javax/swing/JComboBox.java47
-rw-r--r--javax/swing/JComponent.java320
-rw-r--r--javax/swing/JEditorPane.java3
-rw-r--r--javax/swing/JFileChooser.java12
-rw-r--r--javax/swing/JList.java218
-rw-r--r--javax/swing/JMenu.java154
-rw-r--r--javax/swing/JOptionPane.java42
-rw-r--r--javax/swing/JPopupMenu.java11
-rw-r--r--javax/swing/JTabbedPane.java56
-rw-r--r--javax/swing/JTable.java272
-rw-r--r--javax/swing/JTextPane.java19
-rw-r--r--javax/swing/JTree.java57
-rw-r--r--javax/swing/Popup.java2
-rw-r--r--javax/swing/RepaintManager.java18
-rw-r--r--javax/swing/SwingUtilities.java115
-rw-r--r--javax/swing/Timer.java10
-rw-r--r--javax/swing/ToolTipManager.java18
-rw-r--r--javax/swing/UIManager.java5
-rw-r--r--javax/swing/filechooser/FileSystemView.java21
-rw-r--r--javax/swing/filechooser/UnixFileSystemView.java27
-rw-r--r--javax/swing/plaf/basic/BasicButtonListener.java19
-rw-r--r--javax/swing/plaf/basic/BasicButtonUI.java75
-rw-r--r--javax/swing/plaf/basic/BasicComboBoxUI.java41
-rw-r--r--javax/swing/plaf/basic/BasicDirectoryModel.java464
-rw-r--r--javax/swing/plaf/basic/BasicFileChooserUI.java57
-rw-r--r--javax/swing/plaf/basic/BasicHTML.java9
-rw-r--r--javax/swing/plaf/basic/BasicInternalFrameUI.java304
-rw-r--r--javax/swing/plaf/basic/BasicListUI.java5
-rw-r--r--javax/swing/plaf/basic/BasicLookAndFeel.java19
-rw-r--r--javax/swing/plaf/basic/BasicMenuBarUI.java98
-rw-r--r--javax/swing/plaf/basic/BasicMenuItemUI.java13
-rw-r--r--javax/swing/plaf/basic/BasicMenuUI.java207
-rw-r--r--javax/swing/plaf/basic/BasicOptionPaneUI.java204
-rw-r--r--javax/swing/plaf/basic/BasicPopupMenuUI.java670
-rw-r--r--javax/swing/plaf/basic/BasicScrollBarUI.java12
-rw-r--r--javax/swing/plaf/basic/BasicTabbedPaneUI.java1220
-rw-r--r--javax/swing/plaf/basic/BasicTableUI.java329
-rw-r--r--javax/swing/plaf/basic/BasicTextUI.java170
-rw-r--r--javax/swing/plaf/basic/BasicToolBarUI.java180
-rw-r--r--javax/swing/plaf/basic/BasicToolTipUI.java123
-rw-r--r--javax/swing/plaf/basic/BasicTreeUI.java136
-rw-r--r--javax/swing/plaf/metal/MetalBorders.java16
-rw-r--r--javax/swing/plaf/metal/MetalComboBoxButton.java4
-rw-r--r--javax/swing/plaf/metal/MetalFileChooserUI.java134
-rw-r--r--javax/swing/plaf/metal/MetalLookAndFeel.java12
-rw-r--r--javax/swing/plaf/metal/MetalMenuBarUI.java9
-rw-r--r--javax/swing/plaf/metal/MetalTabbedPaneUI.java148
-rw-r--r--javax/swing/plaf/metal/MetalToolTipUI.java70
-rw-r--r--javax/swing/plaf/metal/MetalUtils.java2
-rw-r--r--javax/swing/text/AbstractDocument.java768
-rw-r--r--javax/swing/text/BoxView.java280
-rw-r--r--javax/swing/text/CompositeView.java82
-rw-r--r--javax/swing/text/DefaultCaret.java55
-rw-r--r--javax/swing/text/DefaultHighlighter.java389
-rw-r--r--javax/swing/text/DefaultStyledDocument.java1893
-rw-r--r--javax/swing/text/EmptyAttributeSet.java153
-rw-r--r--javax/swing/text/FlowView.java14
-rw-r--r--javax/swing/text/GapContent.java213
-rw-r--r--javax/swing/text/GlyphView.java29
-rw-r--r--javax/swing/text/IconView.java18
-rw-r--r--javax/swing/text/JTextComponent.java278
-rw-r--r--javax/swing/text/LabelView.java44
-rw-r--r--javax/swing/text/ParagraphView.java44
-rw-r--r--javax/swing/text/PlainView.java150
-rw-r--r--javax/swing/text/Segment.java10
-rw-r--r--javax/swing/text/SimpleAttributeSet.java20
-rw-r--r--javax/swing/text/StringContent.java6
-rw-r--r--javax/swing/text/StyleConstants.java1
-rw-r--r--javax/swing/text/StyledEditorKit.java46
-rw-r--r--javax/swing/text/TabSet.java121
-rw-r--r--javax/swing/text/TabStop.java68
-rw-r--r--javax/swing/text/TextAction.java11
-rw-r--r--javax/swing/text/Utilities.java12
-rw-r--r--javax/swing/text/View.java131
-rw-r--r--javax/swing/text/WrappedPlainView.java24
-rw-r--r--javax/swing/text/html/HTMLDocument.java354
-rw-r--r--javax/swing/text/html/HTMLEditorKit.java9
-rw-r--r--javax/swing/text/html/parser/ParserDelegator.java3
-rw-r--r--javax/swing/tree/TreePath.java2
-rw-r--r--javax/swing/tree/VariableHeightLayoutCache.java4
-rw-r--r--lib/.cvsignore1
-rw-r--r--lib/Makefile.am4
-rwxr-xr-xlib/mkcollections.pl.in3
-rw-r--r--native/jawt/Makefile.am1
-rw-r--r--native/jni/gconf-peer/GConfNativePeer.c654
-rw-r--r--native/jni/gconf-peer/Makefile.am6
-rw-r--r--native/jni/gtk-peer/GtkDragSourceContextPeer.c330
-rw-r--r--native/jni/gtk-peer/Makefile.am3
-rw-r--r--native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c55
-rw-r--r--native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c36
-rw-r--r--native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c32
-rw-r--r--native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice.c4
-rw-r--r--native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c547
-rw-r--r--native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c70
-rw-r--r--native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c36
-rw-r--r--native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c42
-rw-r--r--native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkVolatileImage.c3
-rw-r--r--native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c32
-rw-r--r--native/jni/java-lang/java_lang_VMSystem.c9
-rw-r--r--native/jni/java-net/gnu_java_net_local_LocalSocketImpl.c44
-rw-r--r--native/jni/java-nio/java_nio_VMDirectByteBuffer.c2
-rw-r--r--native/jni/midi-alsa/Makefile.am1
-rw-r--r--native/jni/midi-dssi/Makefile.am1
-rw-r--r--native/jni/qt-peer/Makefile.am1
-rw-r--r--org/omg/CORBA/CompletionStatusHelper.java23
-rw-r--r--org/omg/CORBA/CurrentHelper.java12
-rw-r--r--org/omg/CORBA/DefinitionKindHelper.java39
-rw-r--r--org/omg/CORBA/IDLTypeHelper.java15
-rw-r--r--org/omg/CORBA/NameValuePairHelper.java25
-rw-r--r--org/omg/CORBA/ObjectHelper.java7
-rw-r--r--org/omg/CORBA/ParameterModeHelper.java11
-rw-r--r--org/omg/CORBA/PolicyErrorCodeHelper.java2
-rw-r--r--org/omg/CORBA/PolicyErrorHelper.java32
-rw-r--r--org/omg/CORBA/PolicyHelper.java10
-rw-r--r--org/omg/CORBA/PolicyListHelper.java10
-rw-r--r--org/omg/CORBA/PolicyTypeHelper.java4
-rw-r--r--org/omg/CORBA/ServiceDetailHelper.java40
-rw-r--r--org/omg/CORBA/ServiceInformationHelper.java59
-rw-r--r--org/omg/CORBA/SetOverrideTypeHelper.java29
-rw-r--r--org/omg/CORBA/StringValueHelper.java18
-rw-r--r--org/omg/CORBA/UnionMemberHelper.java2
-rw-r--r--org/omg/CORBA/UnknownUserExceptionHelper.java14
-rw-r--r--org/omg/CORBA/VisibilityHelper.java11
-rw-r--r--org/omg/CORBA/WStringValueHelper.java18
-rw-r--r--org/omg/CORBA/WrongTransactionHelper.java16
-rw-r--r--org/omg/CosNaming/BindingHelper.java32
-rw-r--r--org/omg/CosNaming/BindingIteratorHelper.java10
-rw-r--r--org/omg/CosNaming/BindingListHelper.java19
-rw-r--r--org/omg/CosNaming/BindingTypeHelper.java15
-rw-r--r--org/omg/CosNaming/NameComponentHelper.java34
-rw-r--r--org/omg/CosNaming/NameHelper.java18
-rw-r--r--org/omg/CosNaming/NamingContextExtHelper.java14
-rw-r--r--org/omg/CosNaming/NamingContextExtPackage/AddressHelper.java18
-rw-r--r--org/omg/CosNaming/NamingContextExtPackage/InvalidAddressHelper.java19
-rw-r--r--org/omg/CosNaming/NamingContextExtPackage/StringNameHelper.java17
-rw-r--r--org/omg/CosNaming/NamingContextExtPackage/URLStringHelper.java17
-rw-r--r--org/omg/CosNaming/NamingContextHelper.java10
-rw-r--r--org/omg/CosNaming/NamingContextPackage/AlreadyBoundHelper.java12
-rw-r--r--org/omg/CosNaming/NamingContextPackage/CannotProceedHelper.java32
-rw-r--r--org/omg/CosNaming/NamingContextPackage/InvalidNameHelper.java17
-rw-r--r--org/omg/CosNaming/NamingContextPackage/NotEmptyHelper.java12
-rw-r--r--org/omg/CosNaming/NamingContextPackage/NotFoundHelper.java32
-rw-r--r--org/omg/CosNaming/NamingContextPackage/NotFoundReasonHelper.java24
-rw-r--r--org/omg/DynamicAny/AnySeqHelper.java19
-rw-r--r--org/omg/DynamicAny/DynAnyFactoryHelper.java3
-rw-r--r--org/omg/DynamicAny/DynAnyFactoryPackage/InconsistentTypeCodeHelper.java23
-rw-r--r--org/omg/DynamicAny/DynAnyHelper.java4
-rw-r--r--org/omg/DynamicAny/DynAnyPackage/InvalidValueHelper.java19
-rw-r--r--org/omg/DynamicAny/DynAnyPackage/TypeMismatchHelper.java19
-rw-r--r--org/omg/DynamicAny/DynAnySeqHelper.java16
-rw-r--r--org/omg/DynamicAny/DynArrayHelper.java4
-rw-r--r--org/omg/DynamicAny/DynEnumHelper.java4
-rw-r--r--org/omg/DynamicAny/DynFixedHelper.java4
-rw-r--r--org/omg/DynamicAny/DynSequenceHelper.java4
-rw-r--r--org/omg/DynamicAny/DynStructHelper.java4
-rw-r--r--org/omg/DynamicAny/DynUnionHelper.java4
-rw-r--r--org/omg/DynamicAny/DynValueHelper.java4
-rw-r--r--org/omg/DynamicAny/NameDynAnyPairHelper.java40
-rw-r--r--org/omg/DynamicAny/NameDynAnyPairSeqHelper.java16
-rw-r--r--org/omg/DynamicAny/NameValuePairHelper.java40
-rw-r--r--org/omg/DynamicAny/NameValuePairSeqHelper.java16
-rw-r--r--org/omg/IOP/CodecFactoryHelper.java11
-rw-r--r--org/omg/IOP/CodecFactoryPackage/UnknownEncodingHelper.java18
-rw-r--r--org/omg/IOP/CodecPackage/FormatMismatchHelper.java16
-rw-r--r--org/omg/IOP/CodecPackage/InvalidTypeForEncodingHelper.java23
-rw-r--r--org/omg/IOP/CodecPackage/TypeMismatchHelper.java16
-rw-r--r--org/omg/IOP/ComponentIdHelper.java10
-rw-r--r--org/omg/IOP/IORHelper.java43
-rw-r--r--org/omg/IOP/MultipleComponentProfileHelper.java20
-rw-r--r--org/omg/IOP/ProfileIdHelper.java11
-rw-r--r--org/omg/IOP/ServiceContextHelper.java50
-rw-r--r--org/omg/IOP/ServiceContextListHelper.java11
-rw-r--r--org/omg/IOP/ServiceIdHelper.java4
-rw-r--r--org/omg/IOP/TaggedComponentHelper.java36
-rw-r--r--org/omg/IOP/TaggedProfileHelper.java31
-rw-r--r--org/omg/PortableInterceptor/AdapterManagerIdHelper.java11
-rw-r--r--org/omg/PortableInterceptor/AdapterNameHelper.java23
-rw-r--r--org/omg/PortableInterceptor/AdapterStateHelper.java4
-rw-r--r--org/omg/PortableInterceptor/CurrentHelper.java12
-rw-r--r--org/omg/PortableInterceptor/ForwardRequestHelper.java24
-rw-r--r--org/omg/PortableInterceptor/IORInterceptor_3_0Helper.java11
-rw-r--r--org/omg/PortableInterceptor/InvalidSlotHelper.java16
-rw-r--r--org/omg/PortableInterceptor/ORBInitInfoPackage/DuplicateNameHelper.java33
-rw-r--r--org/omg/PortableInterceptor/ORBInitInfoPackage/InvalidNameHelper.java21
-rw-r--r--org/omg/PortableInterceptor/ObjectReferenceFactoryHelper.java21
-rw-r--r--org/omg/PortableInterceptor/ObjectReferenceTemplateHelper.java21
-rw-r--r--org/omg/PortableInterceptor/ObjectReferenceTemplateSeqHelper.java19
-rw-r--r--org/omg/PortableServer/CurrentHelper.java4
-rw-r--r--org/omg/PortableServer/CurrentPackage/NoContextHelper.java24
-rw-r--r--org/omg/PortableServer/ForwardRequestHelper.java14
-rw-r--r--org/omg/PortableServer/POAHelper.java3
-rw-r--r--org/omg/PortableServer/POAManagerPackage/AdapterInactiveHelper.java16
-rw-r--r--org/omg/PortableServer/POAPackage/AdapterAlreadyExistsHelper.java3
-rw-r--r--org/omg/PortableServer/POAPackage/AdapterNonExistentHelper.java3
-rw-r--r--org/omg/PortableServer/POAPackage/InvalidPolicyHelper.java3
-rw-r--r--org/omg/PortableServer/POAPackage/NoServantHelper.java3
-rw-r--r--org/omg/PortableServer/POAPackage/ObjectAlreadyActiveHelper.java3
-rw-r--r--org/omg/PortableServer/POAPackage/ObjectNotActiveHelper.java3
-rw-r--r--org/omg/PortableServer/POAPackage/ServantAlreadyActiveHelper.java3
-rw-r--r--org/omg/PortableServer/POAPackage/ServantNotActiveHelper.java3
-rw-r--r--org/omg/PortableServer/POAPackage/WrongAdapterHelper.java3
-rw-r--r--org/omg/PortableServer/POAPackage/WrongPolicyHelper.java3
-rw-r--r--org/omg/PortableServer/ServantActivatorHelper.java3
-rw-r--r--org/omg/PortableServer/ServantLocatorHelper.java3
-rw-r--r--resource/META-INF/services/.cvsignore1
-rw-r--r--resource/META-INF/services/javax.sound.sampled.spi.AudioFileReader2
-rw-r--r--resource/gnu/classpath/tools/jarsigner/messages.properties4
-rw-r--r--resource/gnu/java/awt/peer/x/fonts.properties61
-rw-r--r--resource/gnu/java/util/regex/MessagesBundle.properties22
-rw-r--r--resource/gnu/java/util/regex/MessagesBundle_fr.properties22
-rw-r--r--resource/gnu/java/util/regex/MessagesBundle_it.properties31
-rw-r--r--resource/java/security/classpath.security10
-rw-r--r--scripts/Makefile.am2
-rwxr-xr-xscripts/import-cacerts.sh43
-rw-r--r--tools/.cvsignore4
-rwxr-xr-xtools/Makefile.am32
-rw-r--r--tools/gjavah.in47
-rw-r--r--tools/gnu/classpath/tools/jarsigner/SFHelper.java123
-rw-r--r--tools/gnu/classpath/tools/javah/ClassWrapper.java341
-rw-r--r--tools/gnu/classpath/tools/javah/CniIncludePrinter.java69
-rw-r--r--tools/gnu/classpath/tools/javah/CniPrintStream.java243
-rw-r--r--tools/gnu/classpath/tools/javah/CniStubPrinter.java119
-rw-r--r--tools/gnu/classpath/tools/javah/FieldHelper.java97
-rw-r--r--tools/gnu/classpath/tools/javah/JniHelper.java120
-rw-r--r--tools/gnu/classpath/tools/javah/JniIncludePrinter.java151
-rw-r--r--tools/gnu/classpath/tools/javah/JniPrintStream.java115
-rw-r--r--tools/gnu/classpath/tools/javah/JniStubPrinter.java98
-rw-r--r--tools/gnu/classpath/tools/javah/Keywords.java85
-rw-r--r--tools/gnu/classpath/tools/javah/Main.java375
-rw-r--r--tools/gnu/classpath/tools/javah/MethodHelper.java130
-rw-r--r--tools/gnu/classpath/tools/javah/PackageWrapper.java54
-rw-r--r--tools/gnu/classpath/tools/javah/PathOptionGroup.java135
-rw-r--r--tools/gnu/classpath/tools/javah/Printer.java55
-rw-r--r--tools/gnu/classpath/tools/javah/Text.java60
-rw-r--r--tools/gnu/classpath/tools/keytool/Command.java65
-rw-r--r--tools/gnu/classpath/tools/keytool/GenKeyCmd.java3
-rw-r--r--tools/gnu/classpath/tools/keytool/IdentityDBCmd.java2
-rw-r--r--tools/gnu/classpath/tools/keytool/ImportCmd.java3
-rw-r--r--tools/gnu/classpath/tools/keytool/Main.java8
-rw-r--r--vm/reference/gnu/java/lang/management/VMMemoryMXBeanImpl.java4
-rw-r--r--vm/reference/gnu/java/lang/management/VMMemoryPoolMXBeanImpl.java9
-rw-r--r--vm/reference/java/lang/VMSystem.java10
636 files changed, 52816 insertions, 10934 deletions
diff --git a/.classpath b/.classpath
index d89a8d1c4..6f1883b80 100644
--- a/.classpath
+++ b/.classpath
@@ -2,7 +2,7 @@
<classpath>
<classpathentry excluding=".externalToolBuilders/|.settings/|ChangeLog*|Makefile*|autom4te.cache/|compat/|config*|doc/|examples/|external/|external/relaxngDatatype/|include/|install/|lib/|m4/|native/|resource/|scripts/|test/|testsuite/|tools/|vm/reference/|gnu/java/awt/peer/x/" kind="src" path=""/>
<classpathentry excluding=".cvsignore|Makefile|Makefile.am|Makefile.in|README.txt" kind="src" path="external/relaxngDatatype"/>
- <classpathentry excluding=".cvsignore|Makefile|Makefile.am|Makefile.in|README" kind="src" path="tools"/>
+ <classpathentry excluding=".cvsignore|Makefile|Makefile.am|Makefile.in|README|gnu/classpath/tools/javah/" kind="src" path="tools"/>
<classpathentry excluding=".cvsignore|Makefile|Makefile.am|Makefile.in" kind="src" path="resource"/>
<classpathentry excluding=".cvsignore|Makefile.am" kind="src" path="vm/reference"/>
<classpathentry excluding=".cvsignore|Makefile|Makefile.am|Makefile.in|README" kind="src" path="external/sax"/>
diff --git a/ChangeLog b/ChangeLog
index 69ec0ae14..93c4c878b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,3939 @@
+2006-08-13 Roman Kennke <kennke@aicas.com>
+
+ PR 28696
+ * javax/swing/plaf/basic/BasicHTML.java
+ (HTMLRootView.HTMLRootView): Trigger initial layout.
+ (HTMLRootView.setSize): Overridden to forward to real view.
+ * javax/swing/plaf/basic/BasicToolTipUI.java
+ (PropertyChangeHandler): New inner class. Updates the HTML
+ renderer.
+ (propertyChangeHandler): New field.
+ (getMaximumSize): Add HTML width delta.
+ (getMinimumSize): Add HTML width delta.
+ (getPreferredSize): Reimplemented to use HTML view for size
+ calculation if appropriate, otherwise use simple stringWidth()
+ measurement.
+ (installListeners): Install propertyChangeHandler.
+ (uninstallListeners): Uninstall propertyChangeHandler.
+ (installUI): Update HTML renderer.
+ (uninstallUI): Update HTML renderer.
+ (paint): Reimplemented to use HTML view for rendering if
+ appropriate, simple drawString otherwise.
+ * javax/swing/plaf/metal/MetalToolTipUI.java
+ (getPreferredSize): Call super and add accelerator delta.
+ (paint): Simply call super.
+
+2006-08-13 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/JMenu.java
+ (changeListener): Renamed to menuChangeListener to avoid
+ shadowing changeListener field from AbstractButton.
+
+2006-08-13 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/JTree.java
+ (getScrollableUnitIncrement): Fixed direction.
+ (getScrollableBlockIncrement): Implemented to scroll one
+ page.
+ * javax/swing/tree/VariableHeightLayoutCache.java
+ (distance): Consider y + height already outside the node.
+
+2006-08-13 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/JTable.java
+ (getScrollableUnitIncrement): Fixed direction. Make it behave
+ like the RI.
+ (getScrollableBlockIncrement): Fixed direction. Make it behave
+ like the RI.
+
+2006-08-13 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/JList.java
+ (getScrollableUnitIncrement): Fixed direction. Implemented
+ horizontal scrolling. Improved usability.
+ (getScrollableBlockIncrement): Fixed direction. Improved usability.
+
+2006-08-13 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/basic/BasicScrollBarUI.java
+ (scrollByUnit): Scroll by -unit when direction is not positive
+ and +unit otherwise.
+ (scrollByBlock): Scroll by -unit when direction is not positive
+ and +unit otherwise.
+
+2006-08-13 Roman Kennke <kennke@aicas.com>
+
+ PR 28028
+ * javax/swing/text/PlainView.java
+ (paint): Limit painted area to the lines inside the clip
+ and allocation.
+
+2006-08-13 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/basic/BasicTextUI.java
+ (uninstallListeners): Unregister document listener.
+
+2006-08-13 Sven de Marothy <sven@physto.se>
+
+ * java/util/Locale.java
+ (hashcodeCache): New field.
+ (hashCode): use the above field instead of the serialized one
+ (writeObject): Removed method.
+ (readObject): Intern strings.
+ (equals): Revert to previous method.
+
+2006-08-13 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/JTabbedPane.java
+ (JTabbedPane): Call setModel() here and let this install the
+ change listener correctly.
+ (setModel): Correctly uninstall and reinstall ChangeListener when
+ model changes.
+
+2006-08-13 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ PR Classpath/23952
+ * java/util/ResourceBundle.java (CACHE_SIZE): New constant.
+ (bundleCache): Replaced with an LRU of CACHE_SIZE elements.
+ (lastDefaultLocale): Removed.
+ (emptyLocale): Likewise.
+ (BundleKey.defaultLocale): New field.
+ (BundleKey.BundleKey): Add a Locale (as a 1st positional) argument.
+ (BundleKey.set): Likewise.
+ (BundleKey.equals): Take defaultLocal field into consideration.
+ (getBundle(String, Locale, ClassLoader)): Use updated BundleKey and LRU.
+
+2006-08-13 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/JMenu.java
+ (MenuChangeListener): New inner class, helps firing menu events.
+ (changeListener): New field.
+ (add(text)): Create new JMenuItem here and call add(JMenuItem).
+ (add(Action)): Create Action using createActionComponent()
+ and add via add(Component).
+ (setModel): Install and uninstall MenuChangeListener here.
+
+2006-08-13 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ PR Classpath/27372
+ * java/math/BigInteger.java: Updated copyright year.
+ (init): Consume as little bytes as possible.
+ (BigInteger(int, int, Random)): Ensure bitLength bits are used.
+ (valueOf(String, int)): Throw NumberFormatException for malformed strings
+ as per RI's documentation.
+
+2006-08-13 Sven de Marothy <sven@physto.se>
+
+ * java/util/Locale.java
+ (hashcode): Is a serialized field, not transient.
+ (equals): Should NOT compare strings by reference.
+ (readObject/writeObject): Use the default methods and handle the hash
+ seperately.
+
+2006-08-13 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ PR Classpath/28678
+ * gnu/java/security/Engine.java (getInstance(String, String, Provider)):
+ Updated documentation.
+ Formatting.
+ (getInstance(String, String, Provider, Object[])): Likewise.
+ Separate checks for null and empty string arguments.
+ Include as much information as possible in the exception's message.
+ Do not swallow original exception; instead use it as the cause of the
+ resulting exception.
+ * gnu/javax/security/auth/callback/AbstractCallbackHandler.java
+ (getInstance(String)): Updated documentation.
+ Formatting.
+ Store last exception caught when iterating through all providers.
+ If no implementation found, raise last exception if one was caught.
+ (getInstance(String, String)): Updated documentation.
+ Formatting.
+ Check for null or empty provider as per RI-5's documentation.
+ (getInstance(String, Provider)): Updated documentation.
+ Formatting.
+ Use as much information as possible in the exception message.
+ Do not swallow original exception; instead use it as the cause for the
+ ultimate raised exception(s).
+ * java/security/cert/CertificateFactory.java: Likewise.
+ * java/security/cert/CertPathBuilder.java: Likewise.
+ * java/security/cert/CertPathValidator.java: Likewise.
+ * java/security/cert/CertStore.java: Likewise.
+ * java/security/AlgorithmParameterGenerator.java: Likewise.
+ * java/security/AlgorithmParameters.java: Likewise.
+ * java/security/KeyFactory.java: Likewise.
+ * java/security/KeyPairGenerator.java: Likewise.
+ * java/security/KeyStore.java: Likewise.
+ * java/security/MessageDigest.java: Likewise.
+ * java/security/SecureRandom.java: Likewise.
+ * java/security/Signature.java: Likewise.
+ * javax/crypto/Cipher.java: Likewise.
+ * javax/crypto/ExemptionMechanism.java: Likewise.
+ * javax/crypto/KeyAgreement.java: Likewise.
+ * javax/crypto/KeyGenerator.java: Likewise.
+ * javax/crypto/Mac.java: Likewise.
+ * javax/crypto/SecretKeyFactory.java: Likewise.
+ * javax/net/ssl/KeyManagerFactory.java: Likewise.
+ * javax/net/ssl/SSLContext.java: Likewise.
+ * javax/net/ssl/TrustManagerFactory.java: Likewise.
+
+2006-08-13 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/JEditorPane.java
+ (getScrollableTracksViewportHeight): Also check maximum size.
+ * javax/swing/JTextPane.java
+ (insertIcon): Use input attributes for adding the icon
+ attribute.
+ * javax/swing/plaf/basic/BasicTextUI.java
+ (RootView.setSize): Overridden to forward to real view.
+ (getPreferredSize): Trigger setSize() on the view.
+ (viewToModel(JTextComponent,Point)): Pass Position.Bias array
+ to viewToModel() call, rather then null.
+ * javax/swing/text/ParagraphView.java
+ (changedUpdate): Invalide layout. Call super.
+ * javax/swing/text/SimpleAttributeSet.java
+ (clone): Use super's clone method to create clone.
+ * javax/swing/text/StyleConstants.java
+ (setIcon): Also set element name attribute.
+ * javax/swing/text/StyledEditorKit.java
+ (BoldAction.actionPerformed): Actually set the bold attribute,
+ not italic.
+ (setCharacterAttributes): Replaced with more straightforward
+ impl.
+ * javax/swing/text/TextAction.java
+ (getFocusedComponent): Implemented.
+ * javax/swing/text/Utilities.java
+ (getNextVisualPositionFrom): Pass Position.Bias arrays instead
+ of null.
+ * javax/swing/text/View.java
+ (changedUpdate): Nullify element change when updateChildren
+ says so.
+
+2006-08-11 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * vm/reference/gnu/java/lang/management/VMMemoryMXBeanImpl.java:
+ Fix documentation typos.
+
+2006-08-11 David Daney <ddaney@avtrex.com>
+
+ PR classpath/28580
+ * gnu/java/net/protocol/http/Request.java (readResponse): Call
+ createResponseBodyStream in more cases and with new parameter.
+ (createResponseBodyStream): Added new parameter mayHaveBody. Handle
+ HEAD and !mayHaveBody responses specially.
+
+2006-08-11 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/GlyphView.java
+ (DefaultGlyphPainter.modelToView): Fixed model->view mapping.
+ * javax/swing/text/LabelView.java
+ (valid): New flag indicating if the text attributes are valid.
+ (LabelView): Initialize valid field with false.
+ (setPropertiesFromAttributes): Call setter methods instead
+ of setting properties directly. Set valid to true.
+ (changedUpdate): Invalidate attributes. Call super.
+ (getBackground): Sync attributes if necessary.
+ (getForeground): Sync attributes if necessary.
+ (getFont): Sync attributes if necessary.
+ (isUnderline): Sync attributes if necessary.
+ (isSuperscript): Sync attributes if necessary.
+ (isStrikeThrough): Sync attributes if necessary.
+ (getFontMetrics): Sync attributes if necessary. Fetch font metrics
+ from toolkit if Container is not available yet.
+
+2006-08-11 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/PlainView.java
+ (tabBase): New field.
+ (tabSize): New field.
+ (updateMetrics): Update tabSize.
+ (lineToRect): Only allocate when really necessary.
+ (modelToView): Use tabBase for offset calculations.
+ (paint): Only allocate when really necessary. Update tabBase.
+ (nextTabStop): Fixed tab calculation.
+ (viewToModel): Correctly handle multiline text and locations
+ outside the view's bounds. Set bias.
+ (getLineLength): Use tabBase.
+ * javax/swing/text/Utilities.java
+ (drawTabbedText): Don't special case newlines. The views
+ must take care of this.
+
+2006-08-11 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/GapContent.java
+ (UndoPosRef): New inner class. Used for resetting positions
+ after undo/redo operations.
+ (InsertUndo.positions): New field.
+ (InsertUndo.undo): Store positions in removed range.
+ (InsertUndo.redo): Restore positions in re-inserted range.
+ (UndoRemove.positions): New field.
+ (UndoRemove.UndoRemove): Store positions in removed range.
+ (UndoRemove.undo): Restore positions in re-inserted range.
+ (UndoRemove.redo): Store positions in removed range.
+ (insertString): Create InsertUndo instance before actually
+ inserting the string.
+ (remove): Create UndoRemove instance before actually
+ removing.
+ (getPositionsInRange): Don't clear the Vector. Return Vector
+ of UndoPosRefs.
+ (updateUndoPositions): Implemented to reset all UndoPosRefs
+ in the vector.
+
+2006-08-11 Jeroen Frijters <jeroen@frijters.net>
+
+ * java/io/ObjectInputStream.java (readClassDescriptor):
+ Use class's class loader to resolve field types.
+ * java/io/ObjectStreamField.java
+ (ObjectStreamField(String,String,ClassLoader)): Removed.
+ (ObjectStreamField(String,String)): Don't try to resolve typename.
+ (resolveType): New method.
+
+2006-08-10 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/BoxView.java
+ (calculateMajorAxisRequirements): Sum up the preferred and
+ maximum sizes.
+ (isAfter): Also add in the rectangle's with/height.
+ (childAllocation): Don't trigger layout here.
+ (layoutMinorAxis): Removed debug output.
+ (getWidth): Consider the insets.
+ (getHeight): Consider the insets.
+ (setSize): Consider the insets.
+ (updateRequirements): Check axis and throw
+ IllegalArgumentException.
+
+2006-08-10 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/AbstractDocument.java
+ (BidiRootName): New constant field, denotes the element name
+ for bidi root elements.
+ (AsyncLoadPriority): New constant field, denotes the property
+ to store the asynchronousLoadPriority.
+ (I18N): New constant field, denotes the property for
+ I18N support.
+ (bidiRoot): Made field type BidiRootElement.
+ (AbstractDocument): Build initial element structure for
+ bidi.
+ (getAsynchronousLoadPriority): Implemented. Returns the
+ value stored in the document properties.
+ (setAsynchronousLoadPriority): Implemented. Sets the
+ value stored in the document properties.
+ (getEndPosition): Implemented to use a Position from the
+ content.
+ (getStartPosition): Implemented to use a Position from the
+ content.
+ (insertStringImpl): Update the I18N setting if necessary.
+ (insertUpdate): Update the bidi structure if necessary.
+ (postRemoveUpdate): Update the bidi structure if necessary.
+ (putProperty): Update the I18N setting and bidi structure
+ if necessary.
+ (updateBidi): New helper method for updating the bidi
+ structure.
+ (getBidis): New helper method. Fetches the Bidi analysers
+ for the paragraphs of the range to check.
+ (dump): Also dump the bidi structure.
+ (AbstractElement.dump): Indent the '>' correctly.
+ (AbstractElement.children): Check numChildren rather then
+ children.length.
+ (BidiRootElement): New inner class.
+ (BidiElement): New inner class.
+
+2006-08-10 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/GapContent.java
+ (getChars): Optimized to only copy array when really necessary.
+ Respect the partialReturn property.
+
+2006-08-10 Lillian Angel <langel@redhat.com>
+
+ * gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java
+ (getComponentPeer): Added check to prevent NPE.
+
+2006-08-10 Gary Benson <gbenson@redhat.com>
+
+ * java/security/AccessControlContext.java (<init>):
+ Avoid a duplicated AccessController.getContext() call.
+
+2006-08-09 Mark Wielaard <mark@klomp.org>
+
+ * doc/www.gnu.org/newsitems.txt: Add 0.92.
+ * doc/www.gnu.org/downloads/downloads.wml: Likewise.
+ * doc/www.gnu.org/announce/20060809.wml: New file.
+
+2006-08-09 Mark Wielaard <mark@klomp.org>
+
+ * NEWS: Add updates for 0.92 release.
+
+2006-08-09 Tom Tromey <tromey@redhat.com>
+
+ PR classpath/28658:
+ * java/text/SimpleDateFormat.java (parse): Let an unquoted space in
+ the pattern match any number of spaces in the text.
+
+2006-08-09 Sven de Marothy <sven@physto.se>
+
+ * java/awt/image/BufferedImage.java
+ (BufferedImage): Reimplement predefined-type constructor.
+ (observers/tileObservers): Field renamed to tileObservers.
+ (createDefaultIndexedColorModel): New method.
+
+2006-08-09 Tom Tromey <tromey@redhat.com>
+
+ PR classpath/28666:
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice.c
+ (Java_gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice_nativeGetDisplayModes):
+ Create a 'short' array.
+
+2006-08-09 Tom Tromey <tromey@redhat.com>
+
+ * tools/gnu/classpath/tools/javah/JniHelper.java (getName): Properly
+ handle arrays.
+ * tools/gnu/classpath/tools/javah/JniIncludePrinter.java
+ (writeFields): Print "L" after int constant. Don't mangle the field
+ name. Only print int/long fields.
+
+2006-08-09 Tom Tromey <tromey@redhat.com>
+
+ * tools/gnu/classpath/tools/javah/Main.java (getParser): Name program
+ "javah".
+
+2006-08-09 Sven de Marothy <sven@physto.se>
+
+ * javax/swing/JTree.java
+ (JTree): Default SelectionModel should be DefaultTreeSelectionModel.
+ (setSelectionModel): Null parameter should create an EmptySelectionM.
+
+2006-08-09 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/AbstractDocument.java
+ (insertString): Perform modifications inside a write lock.
+ (insertStringImpl): Don't lock here. This is already done
+ in insertString().
+ (replace): Perform modifications inside a write lock.
+ (AbstractElement.AbstractElement): Call addAttributes() to
+ add the attributes.
+ (AbstractElement.getName): Fetch name from the ElementNameAttibute.
+ (BranchElement.lastIndex): New field. Optimizes getElementIndex().
+ (BranchElement.BranchElement): Set lastIndex to -1.
+ (BranchElement.getElementIndex): Implemented more efficient
+ search.
+
+2006-08-09 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/DefaultStyledDocument.java
+ (Edit): Moved this inner class into ElementBuffer where it
+ is actually needed.
+ (edits): Moved this field into ElementBuffer.
+ (getEditForParagraphAndIndex): Removed obsolete method.
+ (insertUpdate): Added some optimizations and fixes. Split
+ out handling insertion after newlines.
+ (insertAfterNewline): New helper method. Handles insertions
+ after a newline.
+ (ElementBuffer.Edit): New inner class. Moved here from
+ DefaultStyledDocument.
+ (ElementBuffer.createdFracture): New field.
+ (ElementBuffer.documentEvent): Made private.
+ (ElementBuffer.edits): New field. Moved here from
+ DefaultStyledDocument.
+ (ElementBuffer.fracNotCreated): Replaced by createdFracture.
+ (ElementBuffer.fracturedChild): New field.
+ (ElementBuffer.fracturedParent): New field.
+ (ElementBuffer.insertPath): New field.
+ (ElementBuffer.lastFractured): Removed. Replaced by fracturedChild and
+ fracturedParent.
+ (ElementBuffer.offsetLastIndex): New field.
+ (ElementBuffer.offsetLastIndexReplace): New field.
+ (ElementBuffer.recreateLeafs): New field.
+ (ElementBuffer.ElementBuffer): Don't initialize stack here.
+ (ElementBuffer.canJoin): New helper method.
+ (ElementBuffer.changeUpdate): Changed to use elementStack with
+ Edits rather than Elements. Let the split method do the work.
+ (ElementBuffer.cloneAsNecessary): New helper method.
+ (ElementBuffer.createFracture): Changed to fracture the bottommost
+ child in the stack.
+ (ElementBuffer.finishEdit): New helper method. Moved out
+ from insertUpdate to perform the actual changes and update
+ the event.
+ (fracture): New helper method.
+ (insertContentTag): Fixed some bugs and changed to use Edit
+ instances in the stack, rather then Elements.
+ (insertElement): New helper method. Moved out from insertUpdate()
+ to process the ElementSpecs.
+ (insertFirstContentTag): Fixed some problems and changed to use Edit
+ instances in the stack, rather then Elements.
+ (insertFracture): Removed. Basically moved into createFracture()
+ and fracture().
+ (insertParagraph): Removed.
+ (insertUpdate): Split out the ElementSpec processing into
+ insertElement(). Use Edit instances in the stack. Fixed some
+ problems.
+ (insert): Split out the preparation and finishing code into
+ prepareEdit() and finishEdit().
+ (join): New helper method.
+ (pop): New helper method.
+ (prepareEdit): New helper method.
+ (recreateFracturedElement): New helper method.
+ (recreateLeaves): Removed.
+ (recreate): New helper method.
+ (removeElements): New helper method. Split out from removeUpdate().
+ (removeUpdate): Split out the actual removal. Use the
+ Edit stack to perform removal and perform the remove actions
+ and event updates afterwards, just like in insertImpl().
+ (remove): Use prepareEdit() and finishEdit().
+ (split): Replaced with more flexible impl.
+
+2006-08-09 Sven de Marothy <sven@physto.se>
+
+ * gnu/java/awt/peer/gtk/CairoSurface.java
+ Change class to extend WritableRaster and not DataBuffer.
+ (CairoDataBuffer): New inner class.
+ * gnu/java/awt/peer/gtk/BufferedImageGraphics.java
+ * gnu/java/awt/peer/gtk/CairoGraphics2D.java
+ * gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
+ Accomodate the above change.
+
+2006-08-09 Sven de Marothy <sven@physto.se>
+
+ * gnu/java/awt/peer/gtk/GtkMainThread.java
+ New file.
+ * gnu/java/awt/peer/gtk/GtkChoicePeer.java
+ * gnu/java/awt/peer/gtk/GtkComponentPeer.java
+ Replace GtkToolkit.mainThread with GtkMainThread.mainThread.
+ * gnu/java/awt/peer/gtk/GtkToolkit.java
+ Minor style fixes; removed unused fields,
+ set fields to private where possible.
+ (createDialog, createFrame, createWindow, createEmbeddedWindow):
+ Call GtkMainThread.createWindow().
+ * gnu/java/awt/peer/gtk/GtkWindowPeer.java
+ (dispose): New method.
+ * include/gnu_java_awt_peer_gtk_GtkToolkit.h
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c
+ (gtkQuit): New native method.
+
+2006-08-08 Lillian Angel <langel@redhat.com>
+
+ * java/awt/Component.java
+ (setDropTarget): Added check.
+
+2006-08-08 Lillian Angel <langel@redhat.com>
+
+ * gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java
+ (GtkDragSourceContextPeer): Added FIXME. Changed call
+ to setTarget.
+ * gnu/java/awt/dnd/peer/gtk/GtkDropTargetContextPeer.java
+ (GtkDropTargetContextPeer): Removed target initialization.
+ * java/awt/Component.java
+ (setTarget): Removed commented out code.
+
+2006-08-08 Mark Wielaard <mark@klomp.org>
+
+ * javax/swing/text/DefaultHighlighter.java: Qualify
+ Highlighter.HighlightPainter class name for gcj.
+
+2006-08-05 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/basic/BasicTableUI.java
+ (MouseInputHandler.mousePressed): Request focus on list
+ component.
+
+2006-08-05 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/basic/BasicListUI.java
+ (MouseInputHandler.mousePressed): Request focus on list
+ component.
+
+2006-08-05 Roman Kennke <kennke@aicas.com>
+
+ PR 28650
+ * javax/swing/plaf/basic/BasicMenuBarUI.java
+ (getActionMap): Store ActionMap in MenuBar.actionMap, rather
+ than Tree.actionMap.
+ * javax/swing/plaf/basic/BasicTreeUI.java
+ (action): Removed obsolete field.
+ (uninstallKeyboardActions): Removed action field handling.
+ (installKeyboardActions): Removed action field handling.
+ (createDefaultActions): Don't install removed TreeAction.
+ (TreeAction): Removed obsolete inner class.
+ (ActionListenerProxy): Removed obsolete inner class.
+ (MouseHandler.mousePressed): Request focus on JTree component
+ on mouse press.
+
+2006-08-05 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/DefaultHighlight.java
+ (DefaultHighlightPainter.paintHighlight): Removed method.
+ (DefaultHighlightPainter.paintLayer): Implemented.
+ (DefaultHighlightPainter.paint): Implemented more efficient
+ painting for multiline-highlights.
+ (HighlightEntry.p0): Changed to be a Position.
+ (HighlightEntry.p1): Changed to be a Position.
+ (HighlightEntry.HighlightEntry): Changed to take Position
+ arfuments.
+ (HighlightEntry.getStartOffset): Changed to return p0.getOffset();
+ (HighlightEntry.getEndOffset): Changed to return p1.getOffset();
+ (LayerHighlightEntry): New inner class. Extends HighlightEntry
+ and tracks the painted rectangle for efficient repainting.
+ (addHighlight): Handle layered highlight.
+ (changeHighlight): Handle layered highlight.
+ (paintLayeredHighlights): Implemented.
+ (paint): Paint only non-layered highlights here.
+ (removeAllHighlights): Trigger correct repaint.
+ (removeHighlight): Handle layered highlight here for
+ more efficient repainting.
+ * javax/swing/text/GlyphView.java
+ (paint): Handle layered highlights.
+ * javax/swing/text/PlainView.java
+ (paint): Handle layered highlights.
+ * javax/swing/text/WrappedPlainView.java
+ (WrappedLine.paint): Handle layered highlights.
+
+2006-08-07 Audrius Meskauskas <AudriusA@Bioinformatics.org>
+
+ PR 26972
+ * NEWS: As suggested by Paul Jennier, added note about the fix of
+ the InitialContext.
+
+2006-08-05 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * gnu/java/lang/management/BeanImpl.java:
+ (getAttribute(String)): Implemented.
+
+2006-08-05 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/JTextComponent.java
+ (AccessibleJTextComponent.dot): Renamed field into caretDot.
+ (AccessibleJTextComponent.textComp): Removed field
+ and replace with JTextComponent.this construct.
+ (AccessibleJTextComponent.AccessibleJTextComponent):
+ Fetch caret position.
+ (caretUpdate): Implemented. Fires property change events and
+ updates the caretDot field.
+ (changedUpdate): Implemented. Fires property change events.
+ (insertUpdate): Implemented. Fires property change events.
+ (removeUpdate): Implemented. Fires property change events.
+ (cut): Replaced textComp with JTextComponent.this construct.
+ (paste): Replaced textComp with JTextComponent.this construct.
+ (replaceText): Replaced textComp with JTextComponent.this construct.
+ (selectText): Replaced textComp with JTextComponent.this construct.
+ (getCaretPosition): Replaced textComp with JTextComponent.this
+ construct.
+ (getCharCount): Replaced textComp with JTextComponent.this construct.
+ (getSelectedText): Replaced textComp with JTextComponent.this
+ construct.
+ (getSelectionEnd): Replaced textComp with JTextComponent.this
+ construct.
+ (getSelectionStart): Replaced textComp with JTextComponent.this
+ construct.
+ (getTextRange): Replaced textComp with JTextComponent.this
+ construct.
+ (doAccessibleAction): Implemented.
+ (getAccessibleActionCount): Implemented.
+ (getAccessibleActionDescription): Implemented.
+ (getAccessibleStateSet): Implemented.
+ (getAfterIndex): Implemented.
+ (getBeforeIndex): Implemented.
+ (getAtIndex): Implemented.
+ (getAtIndexImpl): New helper method.
+ (getCharacterAttribute): Implemented.
+ (getCharacterBounds): Implemented.
+ (getIndexAtPoint): Implemented.
+ (insertTextAtIndex): Implemented.
+ (setAttributes): Implemented.
+ (setTextContents): Implemented.
+
+2006-08-05 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/basic/BasicTextUI.java
+ (modelToView): Read-lock the document. Set size of the
+ root view before fetching the model-to-view mapping.
+ (getViewIndex): Check of the position is inside the range and
+ return -1 if this is not the case.
+ (getViewAtPosition(int,Rectangle): Update child allocation for valid
+ view index.
+ (getViewIndexAtPosition(int)): Delegate the index search to
+ the element since we have a 1:1 mapping between elements and
+ views here.
+ * javax/swing/text/DefaultCaret.java
+ (appear): Ignore BadLocationException.
+ (paint): Ignore BadLocationException.
+ * javax/swing/text/FlowView.java
+ (changedUpdate): Also notify the layoutPool view.
+ (removeUpdate): Also notify the layoutPool view.
+ * javax/swing/text/ParagraphView.java
+ (Row.getViewIndexAtPosition): Overridden to search linearily
+ through the view instead of relying on a 1:1 model to view
+ mapping.
+ * javax/swing/text/View.java
+ (removeUpdate): Clear ElementChange object if updateChildren
+ returns false.
+ (forwardUpdate): Special handle some boundary cases.
+
+2006-08-07 Audrius Meskauskas <AudriusA@Bioinformatics.org>
+
+ * NEWS: Added entry about the context factories for JNDI.
+
+2006-08-07 Audrius Meskauskas <AudriusA@Bioinformatics.org>
+
+ PR 27383
+ * gnu/CORBA/Connected_objects.java (size): New method.
+ * gnu/CORBA/OrbFunctional.java (countConnectedObjects):
+ New method.
+ * javax/naming/spi/NamingManager.java (getURLContext):
+ Also search for the URL context factories in
+ gnu/javax/naming/jndi/url.
+ * gnu/javax/naming/giop/ContextContinuation.java,
+ gnu/javax/naming/giop/CorbalocParser.java,
+ gnu/javax/naming/giop/GiopNamingEnumeration.java,
+ gnu/javax/naming/giop/GiopNamingServiceFactory.java,
+ gnu/javax/naming/giop/GiopNamingServiceURLContext.java,
+ gnu/javax/naming/giop/ListBindingsEnumeration.java,
+ gnu/javax/naming/giop/ListEnumeration.java,
+ gnu/javax/naming/jndi/url/corbaname/corbanameURLContextFactory.java,
+ gnu/javax/naming/jndi/url/rmi/ContextContinuation.java,
+ gnu/javax/naming/jndi/url/rmi/ListBindingsEnumeration.java,
+ gnu/javax/naming/jndi/url/rmi/ListEnumeration.java,
+ gnu/javax/naming/jndi/url/rmi/RmiContinuation.java,
+ gnu/javax/naming/jndi/url/rmi/RmiNamingEnumeration.java,
+ gnu/javax/naming/jndi/url/rmi/rmiURLContext.java,
+ gnu/javax/naming/jndi/url/rmi/rmiURLContextFactory.java: New files.
+
+2006-08-06 Sven de Marothy <sven@physto.se>
+
+ * gnu/java/awt/peer/gtk/CairoGraphics2D.java
+ (drawGlyphVector): Synchronize against font object when drawing.
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c
+ (nativeDrawGlyphVector): Use pango locking when drawing.
+ (install_font_peer): Use pango locking when creating the cairo face.
+
+2006-08-06 C. Scott Marshall <csm@gnu.org>
+
+ Fixes PR 28608.
+ * java/nio/DirectByteBufferImpl.java (duplicate): only reset if
+ the mark has been set.
+ * native/jni/java-nio/java_nio_VMDirectByteBuffer.c
+ (Java_java_nio_VMDirectByteBuffer_allocate): zero out the
+ allocated data.
+
+2006-08-06 Mark Wielaard <mark@klomp.org>
+
+ PR 28555
+ Suggested by Matthew Burgess <matthew@linuxfromscratch.org>
+ * gnu/xml/transform/ApplyTemplatesNode.java (clone): Check whether
+ withParams is null.
+ * gnu/xml/transform/ForEachNode.java (clone): Check whether
+ sortKeys is null.
+
+2006-08-06 Raif S. Naffah <raif@swiftdsl.com.au>
+ Paul Jenner <psj@harker.dyndns.org>
+
+ * README: Update bug, patches and cvs instructions plus new URLs of
+ various external projects.
+
+2006-08-05 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * gnu/java/lang/management/BeanImpl.java:
+ (cacheMBeanInfo(MBeanInfo)): Override given MBeanInfo
+ with open variant.
+ (getCachedMBeanInfo()): Return open variant.
+ (getMBeanInfo()): Likewise.
+ (getTypeFromClass(Class)): Implemented.
+ (translateSignature(MBeanParameterInfo)): Likewise.
+ (translate(String)): Likewise.
+ * javax/management/StandardMBean.java:
+ (getMBeanInfo()): Return attribute names with capital letters,
+ as in docs for java.lang.management.ManagementFactory, and
+ ensure descriptions are not "".
+ * javax/management/openmbean/OpenMBeanConstructorInfoSupport.java,
+ * javax/management/openmbean/OpenMBeanInfoSupport.java,
+ * javax/management/openmbean/OpenMBeanOperationInfoSupport.java:
+ (toString()): Use Arrays.toString().
+ * javax/management/openmbean/OpenMBeanParameterInfoSupport.java:
+ (OpenMBeanParameterInfoSupport(String, String, OpenType)):
+ Set open type here rather than in other constructors.
+
+2006-08-05 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/View.java
+ (modelToView): Added special handling for corner case at the end
+ of the view and for multiline views.
+
+2006-08-05 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/MBeanFeatureInfo.java:
+ Make string variable package-private.
+ * javax/management/StandardMBean.java:
+ (getMBeanInterface()): Made final.
+ * javax/management/openmbean/SimpleType.java:
+ Made final.
+
+2006-08-05 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/basic/BasicTextUI.java
+ (damageRange(JTextComponent,int,int)): Call damageRange() with
+ correct biases, rather than null.
+ (damageRange(JTextComponent,int,int,Bias,Bias)): Rewritten
+ to use simpler modelToView() approach without much special
+ casing. This seems not worth the effort and actually
+ caused problems. Added locking of the document.
+ * javax/swing/text/BoxView.java
+ (requirementsValid): New field.
+ (calculateMajorAxisRequirements): Rewritten without using
+ SizeRequirements. The SizeRequirements algorithms are slightly
+ different and too inefficient.
+ (calculateMinorAxisRequirements): Rewritten without using
+ SizeRequirements. The SizeRequirements algorithms are slightly
+ different and too inefficient.
+ (getAlignment): Simply return the alignment of the cached
+ requirements.
+ (getMaximumSpan): Add insets.
+ (getMinimumSpan): Add insets.
+ (getPreferredSpan): Add insets.
+ (layoutMajorAxis): Rewritten without using
+ SizeRequirements. The SizeRequirements algorithms are slightly
+ different and too inefficient.
+ (layoutMinorAxis): Rewritten without using
+ SizeRequirements. The SizeRequirements algorithms are slightly
+ different and too inefficient.
+ (modelToView): Call setSize() rather than layout().
+ (paint): Check clip for more efficient painting.
+ (preferenceChanged): Invalidate requirements here.
+ (replace): Invalidate requirements here.
+ (updateRequirements): Update requirements only when requirements
+ are marked invalid.
+ * javax/swing/text/CompositeView.java
+ (modelToView): Added some more checks and handling of corner cases.
+ * javax/swing/text/FlowView.java
+ (calculateMinorAxisRequirements): Set aligment to 0.5 and maximum
+ span to Integer.MAX_VALUE. Limit preferredSize to minimumSize.
+ * javax/swing/text/IconView.java
+ (getAlignment): Implemented to return 1.0 for vertical alignment.
+ * javax/swing/text/ParagraphView.java
+ (Row.getMaximumSpan): Implemented to let Rows span the whole
+ ParagraphView.
+ (getAlignment): Fixed horizontal alignment and vertical alignment
+ for empty paragraphs to be 0.5.
+
+2006-08-05 Jeroen Frijters <jeroen@frijters.net>
+
+ * java/awt/Component.java (setDropTarget): Commented out GTK specific
+ code.
+
+2006-08-05 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * gnu/java/security/key/dss/DSSKey.java: Updated documentation.
+ (hasInheritedParameters): New method.
+ (equals): Updated documentation.
+ Take into consideration the outcome of hasInheritedParameters invocation.
+ (toString): Call hasInheritedParameters and adjust the result accordingly.
+ * gnu/java/security/key/dss/DSSKeyPairX509Codec.java (encodePublicKey):
+ Updated documentation.
+ Handle case of public keys with null p, q, and g MPIs.
+ (decodePublicKey): Handle case of absent or NULL p, q and g MPIs.
+
+2006-08-05 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * configure.ac: Better handling of default-preferences-peer option.
+
+2006-08-04 Andreas Tobler <a.tobler@schweiz.ch>
+
+ * java/awt/BasicStroke.java (dashedStroke): Cast coords.clone to
+ double[].
+
+2006-08-04 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/openmbean/TabularData.java:
+ Documentation corrections.
+ * javax/management/openmbean/TabularDataSupport.java:
+ New file.
+
+2006-08-04 Francis Kung <fkung@redhat.com>
+
+ * java/awt/BasicStroke.java
+ (dashedStroke): Implemented.
+
+2006-08-04 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/BadAttributeValueExpException.java,
+ * javax/management/BadStringOperationException.java,
+ * javax/management/InstanceAlreadyExistsException.java,
+ * javax/management/InstanceNotFoundException.java,
+ * javax/management/InvalidApplicationException.java,
+ * javax/management/MBeanRegistrationException.java,
+ * javax/management/MalformedObjectNameException.java,
+ * javax/management/RuntimeErrorException.java,
+ * javax/management/RuntimeMBeanException.java,
+ * javax/management/ServiceNotFoundException.java:
+ New files.
+
+2006-08-04 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/SwingUtilities.java
+ (layoutCompoundLabel(JComponent,FontMetrics,String,Icon,int,int,int,
+ int,Rectangle,Rectangle,Rectangle,int)): Delegate to new
+ layoutCompoundLabelImpl().
+ (layoutCompoundLabel(FontMetrics,String,Icon,int,int,int,int,
+ Rectangle,Rectangle,Rectangle,int)): Delegate to new
+ layoutCompoundLabelImpl().
+ (layoutCompoundLabelImpl): New helper method. Moved impl from
+ layoutCompoundLabel() to here and added handling of HTML.
+ * javax/swing/plaf/basic/BasicButtonUI.java
+ (installUI): Update HTML view if appropriate.
+ (uninstallUI): New method. Do the usual uninstallUI things
+ and uninstall HTML view.
+ (getMinimumSize): New method. Adjusts the minimum size
+ by the HTML view minimum size.
+ (getMaximumSize): New method. Adjusts the maximum size
+ by the HTML view maximum size.
+ (getPreferredSize): Pass the button's iconTextGap to the
+ BasicGraphicsUtils method.
+ (paint): Let HTML view paint the text, if present.
+ * javax/swing/plaf/basic/BasicButtonListener.java
+ (propertyChange): Update the HTML view when the button's
+ text is changed.
+
+2006-08-04 Mario Torre <neugens@limasoftware.net>
+
+ Reported by Raif S. Naffah <raif@swiftdsl.com.au>
+ * native/jni/gconf-peer/GConfNativePeer.c (init_gconf_client):
+ g_type_init earlier in function to correctly initialize the
+ type system used by the backend.
+
+2006-08-04 Audrius Meskauskas <AudriusA@Bioinformatics.org>
+
+ PR 26972
+ * javax/naming/Name.java (addAll, getPrefix, getSuffix):
+ Documented.
+ * gnu/javax/naming/ictxImpl/trans/GnuName.java: New file.
+
+2006-08-04 Robert Schuster <robertschuster@fsfe.org>
+
+ Reported by Henrik Gulbrandsen <henrik@gulbra.net>
+ Fixes PR27864.
+ * gnu/xml/dom/DomIterator.java:
+ (successor): Added if-statement.
+
+2006-08-04 Mark Wielaard <mark@klomp.org>
+
+ * scripts/Makefile.am (EXTRA_DIST): Add import-cacerts.sh.
+
+2006-08-04 Robert Schuster <robertschuster@fsfe.org>
+
+ * javax/swing/plaf/metal/MetalMenuBarUI.java:
+ (update): Check size and paint smaller gradient.
+ * javax/swing/plaf/metal/MetalBorders.java:
+ (MenuBarBorder): Removed borderColor field.
+ (MenuBarBorder.paintBorder): Added note, fetch color from UIManager or
+ MetalLookAndFeel.
+
+2006-08-03 Roman Kennke <kennke@aicas.com>
+
+ PR 27637
+ * javax/swing/plaf/basic/BasicInternalFrameUI.java
+ (ComponentHandler.componentResized): Reimplemented to handle
+ arbitrary parents.
+ (InternalFramePropertyChangeHandler.propertyChange): (Un)install
+ component listener on changed ancestor.
+ (installListeners): Install componentListener.
+ (uninstallListeners): Uninstall componentListener.
+
+2006-08-03 Carsten Neumann <cn-develop@gmx.net>
+
+ * StrictMath.java (cbrt): Return argument if it is a NaN.
+ (cosh): Likewise.
+ (expm1): Likewise.
+ (sinh): Likewise.
+
+2006-08-03 Carsten Neumann <cn-develop@gmx.net>
+
+ * java/lang/StrictMath.java (tanh): New method.
+
+2006-08-03 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * scripts/import-cacerts.sh: Batch CA certificates import script.
+
+2006-08-03 Roman Kennke <kennke@aicas.com>
+
+ PR 28571
+ * gnu/java/awt/peer/gtk/GtkCanvasPeer.java
+ (getPreferredSize): Renamed method to preferredSize(). That's
+ the one that gets called from java.awt.*.
+ * java/awt/peer/ComponentPeer.java
+ (getPreferredSize): Added specnote about this method never
+ beeing called in the RI.
+ (getMinimumSize): Added specnote about this method never
+ beeing called in the RI.
+
+2006-08-03 Sven de Marothy <sven@physto.se>
+
+ * gnu/java/awt/peer/gtk/ComponentGraphics.java
+ (grab, nativeGrab): New methods.
+ * include/gnu_java_awt_peer_gtk_ComponentGraphics.h
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c
+ (nativeGrab): New method.
+ * gnu/java/awt/peer/gtk/GtkComponentPeer.java
+ (print): Implement.
+ * java/awt/Component.java
+ (printAll): Should call peer print method.
+
+2006-08-02 Sven de Marothy <sven@physto.se>
+
+ * gnu/java/awt/peer/gtk/GtkChoicePeer.java
+ (remove): Force event on removing item 0 when it's selected.
+ (handleEvent): Always call Choice.selected().
+ * java/awt/Choice.java:
+ (remove): Simplify and correct.
+
+2006-08-02 Mark Wielaard <mark@klomp.org>
+
+ PR 28535
+ * configure.ac (gconf-peer): Check for gdk-2.0.
+ * native/jni/gconf-peer/Makefile.am
+ (AM_LDFLAGS): Use GDK_LIBS.
+ (AM_CFLAGS): Use GDK_CFLAGS.
+
+2006-08-02 Thomas Minor <1nocentrabidlamb@sexMagnet.com>
+
+ * java/net/URL.java (getContent(Class[])): Implement.
+
+2006-08-02 Roman Kennke <kennke@aicas.com>
+
+ PR 27624
+ * javax/swing/JMenu.java
+ (JMenu()): Removed setting of delay.
+ (JMenu(String)): Removed setting of delay.
+ (JMenu(Action)): Removed setting of delay.
+ (JMenu(String,boolean)): Removed setting of delay.
+ (setSelectedHelper): Removed unneeded method.
+ (setSelected): Simply set the model state.
+ (setPopupMenuVisible): Recognize the popup location
+ determined by getPopupMenuOrigin().
+ (getPopupMenuOrigin): Recognize the UI properties for
+ X and Y offset.
+ (menuSelectionChanged): Call setSelected() directly.
+ * javax/swing/JPopupMenu.java
+ (menuSelectionChanged): If invoker is a JMenu, then delegate
+ to that to get the position right.
+ * javax/swing/Popup.java
+ (LightweightPopup.show): Insert the popup as first component
+ in the layer, so that it overlaps it's caller.
+ * javax/swing/plaf/basic/BasicMenuItemUI.java
+ (getPath): Don't include the popup.
+ * javax/swing/plaf/basic/BasicMenuUI.java
+ (SelectMenuAction): New class. This invokes the popup when
+ a menu is selected.
+ (installDefaults): Install delay of 200 ms.
+ (setupPostTimer): Implemented.
+ (MouseInputHandler.mouseClicked): Do nothing here.
+ (MouseInputHandler.mouseEntered): Use MenuSelectionManager
+ magic to handle the selection. Open the menu via a timer.
+ (MouseInputHandler.mousePressed): Use MenuSelectionManager
+ magic to handle the selection. Open the menu via a timer.
+ (MenuDragMouseHandler.menuMouseDragged): Probably use
+ timer.
+ (menuDragMouseEntered): Do nothing here.
+
+2006-08-02 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/openmbean/InvalidOpenTypeException.java,
+ * javax/management/openmbean/KeyAlreadyExistsException.java:
+ New files.
+
+2006-08-02 Roman Kennke <kennke@aicas.com>
+
+ PR 27606
+ * javax/swing/plaf/basic/BasicListUI.java
+ (paintCell): Pass row index to cell renderer.
+ * javax/swing/plaf/basic/MetalFileChooserUI.java
+ (DirectoryComboBoxRenderer.indentIcon): New field.
+ (DirectoryComboBoxRenderer.DirectoryComboBoxRenderer):
+ Initialize indentIcon.
+ (DirectoryComboBoxRenderer.getListCellRendererComponent):
+ Fall back to super and removed standard functionality.
+ Handle indentation.
+ (IndentIcon): New class. Wraps and indents another icon.
+
+2006-08-02 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/MBeanConstructorInfo.java:
+ (MBeanConstructorInfo(String,String,MBeanParameterInfo[]):
+ Copy array rather than directly assigning.
+ * javax/management/MBeanInfo.java:
+ (MBeanInfo(String,String,MBeanAttributeInfo[],
+ MBeanConstructorInfo[], MBeanOperationInfo[],
+ MBeanNotificationInfo[])): Likewise.
+ * javax/management/MBeanOperationInfo.java:
+ (MBeanOperationInfo(String,String,MBeanParameterInfo[],String,int)):
+ Likewise.
+ * javax/management/openmbean/OpenMBeanAttributeInfoSupport.java,
+ * javax/management/openmbean/OpenMBeanConstructorInfoSupport.java:
+ New files.
+ * javax/management/openmbean/OpenMBeanInfo.java:
+ Corrected documentation.
+ * javax/management/openmbean/OpenMBeanInfoSupport.java:
+ New file.
+ * javax/management/openmbean/OpenMBeanOperationInfo.java:
+ Corrected documentation.
+ * javax/management/openmbean/OpenMBeanOperationInfoSupport.java:
+ New file.
+ * javax/management/openmbean/OpenMBeanParameterInfoSupport.java:
+ (MBeanParameterInfo(String,String,OpenType,Object,Object[])):
+ Call other constructor rather than reimplementing.
+
+2006-08-02 Lillian Angel <langel@redhat.com>
+
+ * java/awt/dnd/DragSource.java
+ (isDragImageSupported): Implemented.
+ (getDragThreshold): Changed default value.
+ * java/awt/dnd/DropTarget.java
+ (DropTarget): Default action is changed to ACTION_COPY_OR_MOVE.
+ (DropTarget): Likewise.
+ (DropTarget): If FlavorMap passed in is null, we should use the system default.
+ (addDropTargetListener): Added check to determine if new DropTargetListener
+ is this class. If so, an IllegalArgumentException is thrown. If the
+ new listener is null, nothing happens.
+
+2006-08-02 Thomas Fitzsimmons <fitzsim@redhat.com>
+
+ * configure.ac (MOZILLA_FOUND): Fall back to
+ mozilla-firefox-plugin.
+
+2006-08-02 Sven de Marothy <sven@physto.se>
+
+ * java/awt/geom/AffineTransform.java
+ (hashCode): Tweak impl.
+ * java/awt/font/FontRenderContext.java
+ (hashCode): Implement.
+
+2006-08-02 Carsten Neumann <cn-develop@gmx.net>
+
+ * java/lang/StrictMath.java (sinh): New method.
+
+2006-08-02 Roman Kennke <kennke@aicas.com>
+
+ PR 27605
+ * javax/swing/JComboBox.java
+ (setSelectedItem): Fire ActionEvent here.
+ * javax/swing/plaf/basic/BasicDirectoryModel.java
+ (directories): Changed to type Vector.
+ (files): New field.
+ (loadThread): New field.
+ (DirectoryLoadThread): New inner class. This loads the contents
+ of directories asynchronously.
+ (getDirectories): Return cached Vector.
+ (getFiles): Return cached Vector.
+ (getSize): Return plain size of contents Vector.
+ (propertyChange): Reread directory also for DIRECTORY_CHANGED,
+ FILE_FILTER_CHANGED, FILE_HIDING_CHANGED and FILE_VIEW_CHANGED.
+ (sort): Don't store sorted list in contents. This must be done
+ asynchronously from the EventThread.
+ (validateFileCache): Rewritten for asynchronous reading
+ of directory contents.
+ * javax/swing/plaf/basic/BasicFileChooserUI.java
+ (installListeners): Install model as PropertyChangeListener.
+ (uninstallListeners): Uninstall model as PropertyChangeListener.
+ (createPropertyChangeListener): Return null just like the
+ RI.
+
+2006-08-02 Roman Kennke <kennke@aicas.com>
+
+ PR 27604
+ * javax/swing/plaf/basic/BasicChooserUI.java
+ (BasicFileView.getName): Fetch the real name from the
+ file chooser's FileSystemView.
+ * javax/swing/plaf/metal/MetalChooserUI.java
+ (DirectoryComboBoxRenderer.getListCellRendererComponent):
+ Set the text fetched from the JFileChooser.getName().
+ * javax/swing/FileSystemView.java
+ (createFileObject): When file is a filesystem root,
+ create a filesystem root object first.
+ (getSystemDisplayName): Return the filename. Added specnote
+ about ShellFolder class that is mentioned in the spec.
+ * javax/swing/UnixFileSystemView.java
+ (getSystemDisplayName): Implemented to return the real name
+ of a file, special handling files like '.' or '..'.
+
+2006-08-02 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ PR Classpath/23899
+ * java/security/SecureRandom.java (next): Call nextBytes as per specs.
+
+2006-08-02 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ PR Classpath/28556
+ * gnu/java/security/key/rsa/RSAKeyPairPKCS8Codec.java (encodePrivateKey):
+ Updated documentation to clarify that RFC-2459 states that the parameters
+ field of the AlgorithmIdentifier element MUST be NULL if present.
+ Amended the code to reflect the specs.
+ (decodePrivateKey): Handle case of NULL AlgorithmIdentifier.parameters.
+
+2006-08-01 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/openmbean/OpenMBeanParameterInfoSupport.java:
+ Call parameter 'defaultValue' not 'defValue'.
+
+2006-08-01 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/openmbean/OpenMBeanParameterInfoSupport.java:
+ New file.
+
+2006-08-01 Roman Kennke <kennke@aicas.com>
+
+ PR 28562
+ * javax/swing/plaf/basic/BasicOptionPaneUI.java
+ (PropertyChangeHandler.propertyChange): Cleanly reinstall
+ components when visual property chanegs.
+
+2006-08-01 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/openmbean/OpenMBeanAttributeInfo.java:
+ (toString()): Corrected documentation.
+ * javax/management/openmbean/OpenMBeanConstructorInfo.java,
+ * javax/management/openmbean/OpenMBeanInfo.java,
+ * javax/management/openmbean/OpenMBeanOperationInfo.java:
+ New files.
+ * javax/management/openmbean/OpenMBeanParameterInfo.java:
+ (toString()): Corrected documentation.
+
+2006-08-01 Tania Bento <tbento@redhat.com>
+
+ * java/awt/Choice.java
+ (remove(int)): Added documentation.
+
+2006-08-01 Tania Bento <tbento@redhat.com>
+
+ * java/awt/Choice.java
+ (remove(int)): An IllegalArgumentException should not be thrown
+ if int is invalid. Update selectedIndex and peer selection.
+
+2006-08-01 Tania Bento <tbento@redhat.com>
+
+ * java/awt/CardLayout.java
+ (toString): Changed format of string outputted.
+ (goToComponent): Changed the order of the if-clause.
+
+2006-08-01 Tania Bento <tbento@redhat.com>
+
+ * java/awt/List.java
+ (select): Check if selected is null before execution of
+ for-loop. If it is null, selected is instantiated and
+ the index is added to it.
+
+2006-08-01 Roman Kennke <kennke@aicas.com>
+
+ PR 28562
+ * javax/swing/plaf/basic/BasicOptionPaneUI.java
+ (PropertyChangeHandler.propertyChange): Uninstall and reinstall
+ component when visual properties change.
+
+2006-08-01 Roman Kennke <kennke@aicas.com>
+
+ PR 28534
+ * javax/swing/JTree.java
+ (JTree(TreeModel)): Set cell renderer to null.
+ * javax/swing/plaf/basic/BasicTreeUI.java
+ (setCellRenderer): Finish editing before setting the
+ cell renderer. Refresh the layout. Don't set the
+ currentCellRenderer field here (that's done in updateRenderer).
+ (updateRenderer): Handle createdRenderer field here too.
+ Set renderer to a default handler when the current renderer
+ in the JTree is null.
+
+2006-07-31 Tom Tromey <tromey@redhat.com>
+
+ * INSTALL: Updated for ASM.
+
+2006-07-31 Tom Tromey <tromey@redhat.com>
+
+ PR libgcj/23682:
+ * java/nio/channels/SelectionKey.java (attach): Now synchronized.
+ (attachment): Likewise.
+ * java/nio/channels/spi/AbstractSelectionKey.java (cancel): Now
+ synchronized.
+ (isValid): Likewise.
+ * gnu/java/nio/SelectionKeyImpl.java (impl): Now final
+ (ch): Likewise.
+ (interestOps): Synchronize.
+ (readyOps): Likewise.
+ * gnu/java/nio/SelectorImpl.java (register): Synchronize around
+ interestOps call.
+
+2006-07-31 Roman Kennke <kennke@aicas.com>
+
+ * NEWS: Added note about the X peers.
+ * INSTALL: Added install notes about the X peers.
+
+2006-07-31 Carsten Neumann <cn-develop@gmx.net>
+
+ * StrictMath.java (getLowDWord): Return long instead of int.
+ (getHighDWord): Likewise.
+ (buildDouble): Take two long arguments.
+ (cbrt): Adapted to int -> long change.
+ (expm1): Likewise.
+ (cosh): Likewise.
+
+2006-07-31 Thomas Fitzsimmons <fitzsim@redhat.com>
+
+ * native/jni/qt-peer/Makefile.am (libqtpeer_la_LDFLAGS): Add
+ -avoid-version.
+
+2006-07-31 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * java/security/Provider.java: Updated copyright year.
+ Updated documentation.
+ Formatting.
+ (put): Updated documentation.
+ Added security manager check.
+ Canonicalize the key before adding its mapping.
+ (get): Override superclass implementation to use canonicalized keys.
+ (remove): Updated documentation.
+ Added security manager check.
+ Canonicalize the key before removing its mapping.
+ (clear): Updated documentation.
+ Added security manager check.
+ (toCanonicalKey): New method.
+
+2006-07-30 Mark Wielaard <mark@klomp.org>
+
+ * resource/java/security/classpath.security: Add /dev/urandom as
+ default securerandom.source.
+
+2006-07-30 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/openmbean/OpenMBeanAttributeInfo.java,
+ * javax/management/openmbean/OpenMBeanParameterInfo.java:
+ New files.
+
+2006-07-30 Mark Wielaard <mark@klomp.org>
+
+ * java/util/GregorianCalendar.java (maximums): Months can have up to
+ 6 weeks.
+ (nonLeniencyCheck): weeks is either 5 or 6.
+
+2006-07-30 Matt Wringe <mwringe@redhat.com>
+
+ * gnu/java/security/Engine.java
+ (getInstance): Ignore self referencing aliases.
+
+2006-07-30 Sven de Marothy <sven@physto.se>
+
+ * java/awt/Choice.java:
+ (accessibleAction): Call select() directly.
+ (add, insert, remove): Reimplement.
+ (dispatchEventImpl): Always call super.
+ (processItemEvent): Does not set the index.
+ * include/gnu_java_awt_peer_gtk_GtkChoicePeer.h
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c
+ (append): removed.
+ (nativeAdd): Name changed to add.
+ (selection_changed_cb): Simplify callback.
+ * gnu/java/awt/peer/gtk/GtkChoicePeer.java
+ (selected): New field.
+ (add): Replaced with native impl.
+ (handleEvent): New method.
+
+2006-07-30 Sven de Marothy <sven@physto.se>
+
+ * java/awt/Choice.java:
+ Reformat, fix copyright year.
+
+2006-07-29 Mark Wielaard <mark@klomp.org>
+
+ * javax/swing/JComponent.java (paintingDoubleBuffered): Renamed
+ static field isPaintingDoubleBuffered to not have the same name
+ as a method.
+
+2006-07-29 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * examples/gnu/classpath/examples/management/TestBeans.java:
+ New file.
+ * javax/management/MBeanAttributeInfo.java:
+ (toString()): Implemented.
+ * javax/management/MBeanConstructorInfo.java:
+ (toString()): Implemented.
+ * javax/management/MBeanFeatureInfo.java:
+ (toString()): Implemented.
+ * javax/management/MBeanInfo.java:
+ (toString()): Implemented.
+ * javax/management/MBeanNotificationInfo.java:
+ (toString()): Implemented.
+ * javax/management/MBeanOperationInfo.java:
+ (toString()): Implemented.
+ * javax/management/MBeanParameterInfo.java:
+ (toString()): Implemented.
+ * javax/management/StandardMBean.java:
+ (getMBeanInfo()): Fix attribute naming.
+
+2006-07-29 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * gnu/java/lang/management/BeanImpl.java:
+ Extended javax.management.StandardMBean.
+ * gnu/java/lang/management/ClassLoadingMXBeanImpl.java,
+ * gnu/java/lang/management/CompilationMXBeanImpl.java,
+ * gnu/java/lang/management/GarbageCollectorMXBeanImpl.java,
+ * gnu/java/lang/management/MemoryMXBeanImpl.java,
+ * gnu/java/lang/management/MemoryManagerMXBeanImpl.java,
+ * gnu/java/lang/management/MemoryPoolMXBeanImpl.java,
+ * gnu/java/lang/management/OperatingSystemMXBeanImpl.java,
+ * gnu/java/lang/management/RuntimeMXBeanImpl.java,
+ * gnu/java/lang/management/ThreadMXBeanImpl.java:
+ Call the superclass with the appropriate class.
+ * java/lang/management/ManagementFactory.java:
+ (getOperatingSystemMXBean()): Catch exception from
+ StandardMBean.
+ (getRuntimeMXBean()): Likewise.
+ (getClassLoadingMXBean()): Likewise.
+ (getThreadMXBean()): Likewise.
+ (getMemoryMXBean()): Likewise.
+ (getCompilationMXBean()): Likewise.
+ (getMemoryPoolMXBeans()): Likewise.
+ (getMemoryManagerMXBeans()): Likewise.
+ (getGarbageCollectorMXBeans()): Likewise.
+ * javax/management/MBeanFeatureInfo.java:
+ (hashCode()): Fixed to check for null values.
+
+2006-07-28 Thomas Fitzsimmons <fitzsim@redhat.com>
+
+ * native/jawt/Makefile.am (libjawt_la_LDFLAGS): Add
+ -avoid-version.
+ * native/jni/gtk-peer/Makefile.am (libgtkpeer_la_LDFLAGS):
+ Likewise.
+ * native/jni/midi-alsa/Makefile.am (libgjsmalsa_la_LDFLAGS):
+ Likewise.
+ * native/jni/midi-dssi/Makefile.am (libgjsmdssi_la_LDFLAGS):
+ Likewise.
+
+2006-07-28 Tom Tromey <tromey@redhat.com>
+
+ * configure.ac: Enable -Werror by default on Linux-with-gcc.
+
+2006-07-28 Lillian Angel <langel@redhat.com>
+
+ * native/jni/gtk-peer/GtkDragSourceContextPeer.c:
+ Removed function declarations.
+ (connect_signals_for_widget): Removed implementation because
+ stub functions have been removed.
+ (drag_begin_cb): Removed function.
+ (drag_motion_cb): Likewise.
+ (drag_data_get_cb): Likewise.
+ (drag_data_delete_cb): Likewise.
+ (drag_drop_cb): Likewise.
+ (drag_end_cb): Likewise.
+ (drag_data_received_cb): Likewise.
+
+2006-07-28 Mark Wielaard <mark@klomp.org>
+
+ * configure.ac: Set version to 0.93-pre.
+
+2006-07-29 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * tools/Makefile.am: Added source 1.4 compliance option when ECJ is used.
+
+2006-07-29 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * tools/gnu/classpath/tools/keytool/Command.java: Removed unused import.
+ (getCallbackHandler): Fully qualify linked class in javadoc.
+ * tools/gnu/classpath/tools/keytool/GenKeyCmd.java (cmdOptionsParser): Removed.
+ * tools/gnu/classpath/tools/keytool/ImportCmd.java (imported): Likewise.
+ * tools/gnu/classpath/tools/keytool/Main.java (printHelp): Likewise.
+
+2006-07-28 Matt Wringe <mwringe@redhat.com>
+
+ * gnu/java/security/Engine.java
+ (getInstance): Add case insentivity to algorithm names
+ * java/security/Provider.java
+ (put): Stop using canonical key naming
+ (remove): Likewise
+ (toCanonicalKey): Method removed
+ (get): Method removed, no longer needs to overwrite
+ parent implementation
+
+2006-07-28 Lillian Angel <langel@redhat.com>
+
+ * gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java
+ (GtkDragSourceContextPeer): Added check to avoid NPE.
+
+2006-07-28 Lillian Angel <langel@redhat.com>
+
+ * native/jni/gtk-peer/GtkDragSourceContextPeer.c:
+ (Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_create):
+ Fixed to use gref not ptr.
+
+2006-07-28 Lillian Angel <langel@redhat.com>
+
+ * native/jni/gtk-peer/GtkDragSourceContextPeer.c:
+ Added new static helper function.
+ (Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_connectSignals):
+ Moved code to connect signals to the helper function.
+ (Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_create):
+ Removed ptr field and changed to use global gref.
+ (connect_signals_for_widget): Implemented new helper.
+ (setTarget): Added call to connect_signals_for_widget.
+
+2006-07-28 Lillian Angel <langel@redhat.com>
+
+ * native/jni/gtk-peer/GtkDragSourceContextPeer.c:
+ Added more static functions to handle widget signals.
+ (create): Initialized the javaObj field.
+ (connectSignals): Added code to connect all signals to
+ the appropriate functions and initialized all java
+ function fields.
+ (drag_begin_cb): New callback, not implemented.
+ (drag_motion_cb): Likewise.
+ (drag_data_get_cb): Likewise.
+ (drag_data_delete_cb): Likewise.
+ (drag_drop_cb): Likewise.
+ (drag_end_cb): Likewise.
+ (drag_data_received_cb): Likewise.
+ (setTarget): New function.
+ (nativeStartDrag): Added code to set the destination and source
+ widgets.
+ * java/awt/dnd/DragSource.java
+ (startDrag): Removed FIXME.
+ * java/awt/dnd/DragGestureRecognizer.java
+ (fireDragGestureRecognized): Reset recognizer when events are fired.
+ * java/awt/Component.java
+ (setDropTarget): Added code to create the DropTargetContextPeer.
+ * include/GtkDragSourceContextPeer.h: Regenerated.
+ * gnu/java/awt/dnd/peer/gtk/GtkDropTargetPeer.java: Removed file.
+ * gnu/java/awt/dnd/peer/gtk/GtkDropTargetContextPeer.java
+ (GtkDropTargetContextPeer): Implemented.
+ * gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java
+ (GtkDragSourceContextPeer): Added code to set the target.
+
+2006-07-28 Tom Tromey <tromey@redhat.com>
+
+ * NEWS: Updated.
+ * .classpath: Updated.
+ * tools/.cvsignore: Added gjavah.
+ * tools/Makefile.am ($(TOOLS_ZIP)): Only build javah if ASM is
+ available.
+ (GLIBJ_CLASSPATH): Add asm jar.
+ (javah): New macro.
+ (bin_PROGRAMS, bin_SCRIPTS): Added $(javah).
+ (gjavah_SOURCES, gjavah_CFLAGS, gjavah_LDFLAGS): new macros.
+ * tools/gjavah.in: New file.
+ * configure.ac: Added --with-asm option.
+ * tools/gnu/classpath/tools/javah/ClassWrapper.java: New file.
+ * tools/gnu/classpath/tools/javah/CniIncludePrinter.java: Likewise.
+ * tools/gnu/classpath/tools/javah/CniPrintStream.java: Likewise.
+ * tools/gnu/classpath/tools/javah/CniStubPrinter.java: Likewise.
+ * tools/gnu/classpath/tools/javah/FieldHelper.java: Likewise.
+ * tools/gnu/classpath/tools/javah/JniHelper.java: Likewise.
+ * tools/gnu/classpath/tools/javah/JniIncludePrinter.java: Likewise.
+ * tools/gnu/classpath/tools/javah/JniStubPrinter.java: Likewise.
+ * tools/gnu/classpath/tools/javah/Keywords.java: Likewise.
+ * tools/gnu/classpath/tools/javah/Main.java: Likewise.
+ * tools/gnu/classpath/tools/javah/MethodHelper.java: Likewise.
+ * tools/gnu/classpath/tools/javah/PackageWrapper.java: Likewise.
+ * tools/gnu/classpath/tools/javah/PathOptionGroup.java: Likewise.
+ * tools/gnu/classpath/tools/javah/Printer.java: Likewise.
+ * tools/gnu/classpath/tools/javah/Text.java: Likewise.
+
+2006-07-28 Anthony Balkissoon <abalkiss@redhat.com>
+
+ * java/awt/List.java: Committed following patch from Tania.
+ Initialized private variable visibleIndex to -1.
+ (addItem(String, int)): If string is null, set to empty string. If int
+ < -1, set to -1.
+ (delItem): If the item to be deleted was selected, select the next
+ item in the list.
+ (delItems): Checks are not necessary and all indices in selected should
+ be deleted.
+ (select): Update selected.
+ (deselect): Update selected.
+
+2006-07-27 Roman Kennke <kennke@aicas.com>
+
+ * java/awt/Component.java
+ (getToolkit): Search for heavyweight parent and query the
+ heavyweight's peer.
+ (checkImage(Image,int,int,ImageObserver)): Likewise.
+ (checkImage(ImageProducer)): Likewise.
+ (createImage(int,int)): Likewise.
+ (createVolatileImage(int,int)): Likewise.
+ (createVolatileImage(int,int,ImageCapabilities)): Likewise.
+ (getFontMetrics): Likewise.
+ (getGraphics): Likewise.
+ (getLocationOnScreen): Likewise.
+ (prepareImage): Likewise.
+ (setCursor): Likewise.
+ (repaint): Added null check.
+ (addNotify): Send hierarchy event.
+ (removeNotify): Send hierarchy event.
+ (disableEvents): Update hierarchy listener counters.
+ (enableEvents): Update hierarchy listener counters.
+ (isHierarchyVisible): New helper method.
+ (notifyReshape): Do Container specific handling in
+ Container.
+ * java/awt/Container.java
+ (insets): For lightweights, return (0,0,0,0).
+ * java/awt/Toolkit.java
+ (lightweightPeer): New static field.
+ (createComponent): Return shared instance of GLightweightPeer.
+ (notifyReshape): Override Component method to add some handling
+ that is specific for Container.
+ (removeAll): Also send hierarchy and container events here.
+ Update the hierarchy listener counters.
+ * gnu/java/awt/peer/GLightweightPeer.java: Made all methods
+ stubs and added comment.
+
+2006-07-27 Sven de Marothy <sven@physto.se>
+
+ * java/math/BigDecimal.java
+ Adjust copyright date.
+ (divide(BigDecimal): Implement.
+ (precision): Reimplement.
+ (numDigitsInBigInteger, numDigitsInLong): Removed.
+ (toString): Get exponent from string length,
+ fix negative values with exponential form.
+ (toEngineeringString): Same as for toString.
+ (setScale): Throw ArithmeticException if scale < 0.
+
+2006-07-27 Francis Kung <fkung@redhat.com>
+
+ * gnu/java/awt/java2d/CubicSegment.java: Added import.
+ (cp1): Renamed from first().
+ (c2): Renamed from last().
+ (first): Renamed to cp1().
+ (getDisplacedSegments): Implemented.
+ (last): Renamed to cp2().
+ * gnu/java/awt/java2d/LineSegment.java
+ (cp1): Renamed from first().
+ (c2): Renamed from last().
+ (first): Renamed to cp1().
+ (last): Renamed to cp2().
+ * gnu/java/awt/java2d/QuadSegment.java
+ (cp1): Renamed from first().
+ (c2): Renamed from last().
+ (first): Renamed to cp1().
+ (last): Renamed to cp2().
+ * gnu/java/awt/java2d/Segment.java: Added comments.
+ (first): New field.
+ (Segment): Keep track of first element in list.
+ (add): Update first & last element variables.
+ (cp1): Renamed from first().
+ (c2): Renamed from last().
+ (first()): Renamed to cp1() to reduce ambiguity.
+ (last()): Renamed to cp2() to reduce ambiguity.
+ (reverseAll): Update first element variable..
+ * gnu/java/awt/peer/gtk/CairoGraphics2D.java
+ (draw): Remove flattening path iterator.
+ * java/awt/BasicStroke.java: Clarified comments.
+ (addSegments): Refactored some code into joinSegments and
+ joinInnerSegments.
+ (capEnd): Rename of Segment.first() and Segment.end().
+ (joinInnerSegments): New method.
+ (joinOuterSegments): New method.
+ (joinSegments): Refactored some code into joinOuterSegments.
+ (solidStroke): Connect segments together properly.
+
+2006-07-27 Tom Tromey <tromey@redhat.com>
+
+ PR classpath/28486:
+ * java/net/URLStreamHandler.java (equals): Properly handle default
+ port. Rewrote javadoc. Don't compare 'authority' parts of URLs.
+
+2006-07-27 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/AbstractDocument.java
+ (documentCV): Made field private.
+ (bypass): Made field private.
+ (bidiRoot): New field.
+ (AbstractDocument): Initialize bidiRoot.
+ (getBidiRootElement): Return bidiRoot.
+ (getRootElements): Adjusted to also return the bidiRoot element.
+ (BranchElement.startOffset): Removed unneeded field.
+ (BranchElement.endOffset): Removed unneeded field.
+ (BranchElement.BranchElement): Removed unneeded fields.
+ (BranchElement.getEndOffset): Don't explicitly throw NPE here. This is
+ done automatically when there's no element left in the array.
+ (BranchElement.getStartOffset): Likewise.
+ (BranchElement.replace): Reordered calculations to avoid double
+ calculations.
+ (removeImpl): Silently ignore requests with length <= 0.
+ * javax/swing/text/GapContent.java
+ (createPosition): Removed explicit check for correct offset.
+ This class can deal with offsets outside the document.
+ (shiftEnd): Update all positions, even those outside the
+ document.
+ (adjustPositionsInRange): Fixed to also adjust positions outside
+ the document boundary.
+
+2006-07-18 Kyle Galloway <kgallowa@redhat.com>
+
+ * gnu/classpath/jdwp/event/ExceptionEvent.java: Added _klass field to hold
+ defining class.
+ (getParameter): Returns _klass field instead of determining
+ class from _instance.
+ (setCatchLoc): New method.
+ (writeData): Now assumes Location deals with empty locations instead of
+ using null.
+ * gnu/classpath/jdwp/util/Location.java (write): Check for empty
+ locations and write out accordingly.
+ (getEmptyLocation): New method.
+
+2006-07-27 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/SimpleAttributeSet.java
+ (EMPTY): Use EmptyAttributeSet for this field rather than
+ SimpleAttributeSet.
+ * javax/swing/text/EmptyAttributeSet.java: New class. Implements
+ an empty and immutable AttributeSet.
+
+2006-07-27 Roman Kennke <kennke@aicas.com>
+
+ * java/awt/Component.java
+ (reshape): Invalidate the component itself only when the
+ size has changed. Invalidate the parent always. Fixed
+ repainting. Pulled out the notification into
+ notifyReshape().
+ (notifyReshape): New helper method. Notify interested listeners
+ about a reshape.
+ (update): Simply call paint() without clearing the background.
+ This is done in Container.update() if appropriate.
+ (repaint): Delagate the repaint to the nearest heavyweight
+ parent (for lightweights) and send an UPDATE event, rather than
+ calling ComponentPeer.repaint().
+ * java/awt/Container.java
+ (backCleared): Removed field.
+ (paint): Removed handling of backCleared flag.
+ (update): Only paint if the container is actually
+ showing. Removed handling of backCleared flag.
+
+2006-07-27 Robert Schuster <robertschuster@fsfe.org>
+
+ * javax/swing/plaf/basic/BasicTabbedPaneUI.java: Fixed copyright and
+ authorship.
+ (NavigateAction): New inner class.
+ (NavigatePageDownAction): New inner class.
+ (NavigatePageUpAction): New inner class.
+ (RequestFocusAction): New inner class.
+ (RequestFocusForVisibleComponentAction): New inner class.
+ (FocusHandler.focusGained): Implemented.
+ (FocusHandler.focusLost): Implemented.
+ (MouseHandler.mouseReleased): Implemented.
+ (MouseHandler.mousePressed): Rewritten.
+ (PropertyChangeHandler.propertyChange): Reset currentScrollOffset and
+ currentScrollLocation to 0.
+ (TabbedPaneLayout.calculateSize): Stored tab count in local variable,
+ removed local variables, fixed indentation to stay under 80 column
+ limit.
+ (TabbedPaneLayout.calculateTabRects): Decrease tab area position by
+ one, set selectedIndex to 0 if its negative, corrected start values
+ for normalization, suppressed padding when only one tab run,
+ (TabbedPaneLayout.minimumLayoutSize): Toggled argument value.
+ (TabbedPaneLayout.normalizeTabRuns): Fixed indentation to stay under
+ 80 column limit, corrected the starting value for the bounds fixing
+ phase.
+ (TabbedPaneLayout.preferredTabAreaWidth): Fixed indentation.
+ (TabbedPaneLayout.rotateTabInRuns): Corrected comparison value for
+ selectedRun, set start index for loop to 0.
+ (TabbedPaneScrollLayout.preferredLayoutSize): Toggled argument value.
+ (TabbedPaneScrollLayout.calculateTabRects): Rewritten.
+ (TabbedPaneScrollLayout.layoutContainer): Added scrolling button
+ alignment and visibility handling.
+ (TabSelectionHandler.stateChanged): Do revalidation only in wrap tab
+ layout mode.
+ (ScrollingPanel.ScrollingPanelUI.paint): Rewritten.
+ (currentScrollOffset): New field.
+ (tabRuns): Rewritten documentation.
+ (selectedColor): New field.
+ (tempTextRect): New field.
+ (tempIconRect): New field.
+ (scrollTab): New method.
+ (updateButtons): New method.
+ (updateViewPosition): New method.
+ (createLayoutManager): Reordered method calls, predefine new fields,
+ register proper listeners.
+ (uninstallComponents): Implemented.
+ (installDefaults): Corrected property names, fixed indentation,.
+ (uninstallDefaults): Set new fields to null.
+ (uninstallListeners): Remove listeners from components neccessary for
+ scrolling tab layout.
+ (installKeyboardActions): Implemented.
+ (uninstallKeyboardActions): Implemented.
+ (paint): Paint tab area background.
+ (paintTabArea): Fixed indentation, removed usage of local Rectangle
+ objects.
+ (getTabLabelShiftX): Rewritten.
+ (getTabLabelShiftY): Rewritten.
+ (paintFocusIndicator): Reindented.
+ (paintTabBorder): Rewritten.
+ (paintTabBackground): Corrected color usage, rewritten background
+ rectangle painting.
+ (paintContentBorderTopEdge): Rewritten.
+ (paintContentBorderBottomEdge): Rewritten.
+ (paintContentBorderLeftEdge): Rewritten.
+ (paintContentBorderRightEdge): Rewritten.
+ (tabForCoordinate): Return selected index when no tab could be
+ found, removed FIXME note.
+ (getRunForTab): Changed return value for first if-statement.
+ (navigateSelectedTab): Fixed last argument for both
+ getTabRunOffset() calls.
+ (selectedNextTabInRun): Added scrolling code.
+ (selectedPreviousTabInRun): Added scrolling code.
+ (selectedNextTab): Added scrolling code.
+ (selectedPreviousTab): Added scrolling code.
+ (selectAdjacentRunTab): Added scrolling code.
+ (getTextViewForTab): Added FIXME note.
+ (calculateTabHeight): Changed FIXME note.
+ (getTabRunOffset): Fixed indentation.
+ (getNextTabIndexInRun): Corrected return value.
+ (rotateInsets): Make TOP case the default in switch-statement.
+ (getActionMap): New method.
+ (createActionMap): New method.
+ * javax/swing/plaf/metal/MetalTabbedPaneUI.java:
+ (createLayoutManager): Rewritten.
+ (paintLeftTabBorder): Do not paint left line when previous tab
+ is selected but current tab is the first in its run, do not paint
+ left line when current tab is selected and is first in its run.
+ (paintRightTabBorder): Added missing setColor() call, fixed color
+ usage, do not paint right line if previous tab is selected but
+ current tab is the first in its run.
+ (paintBottomTabBorder): Do not paint left line if tab is selected
+ and is the first tab in the last run.
+ (paintFocusIndicator): New method.
+ (getLabelShiftX): New method.
+ (getLabelShiftY): New method.
+
+2006-07-27 Andreas Tobler <a.tobler@schweiz.ch>
+
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c
+ (Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetMatrix): Remove
+ g_assert from unused obj.
+ (Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoDrawGlyphVector): Mark
+ obj as unused and remove g_assert on it.
+
+2006-07-26 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/RepaintManager.java
+ (markCompletelyDirty): Add dirty region with Integer.MAX_VALUE
+ for the component.
+ (isCompletelyDirty): Consider a component completely dirty
+ when it has a dirty region with Integer.MAX_VALUE.
+
+2006-07-26 Roman Kennke <kennke@aicas.com>
+
+ * java/awt/KeyboardFocusManager.java
+ (getGlobalFocusOwner): Explicitly check for thread security.
+ (getGlobalPermanentFocusOwner): Explicitly check for thread security.
+ (getGlobalFocusedWindow): Explicitly check for thread security.
+ (getGlobalActiveWindow): Explicitly check for thread security.
+ (getGlobalCurrentFocusCycleRoot): Explicitly check for thread security.
+ (getGlobalObject): Added new argument for specifying if
+ a security check should be performed or not.
+ (setGlobalObject): Don't check for thread security when
+ calling getGlobalObject.
+
+2006-07-26 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/MBeanConstructorInfo.java:
+ Documentation fix.
+ * javax/management/MBeanInfo.java:
+ (MBeanInfo(String,String,MBeanAttributeInfo[],
+ MBeanConstructorInfo[], MBeanOperationInfo[],
+ MBeanNotificationInfo[])): Implemented.
+ (equals(Object)): Likewise.
+ (getAttributes()): Likewise.
+ (getConstructors()): Likewise.
+ (getOperations()): Likewise.
+ (hashCode()): Likewise.
+ * javax/management/MBeanOperationInfo.java,
+ * javax/management/NotCompliantMBeanException.java,
+ * javax/management/StandardMBean.java:
+ New files.
+
+2006-07-26 Sven de Marothy <sven@physto.se>
+
+ * java/awt/geom/GeneralPath.java: Fix severe typo.
+
+2006-07-26 Sven de Marothy <sven@physto.se>
+
+ * include/java_lang_VMSystem.h
+ * vm/reference/java/lang/VMSystem.java
+ * native/jni/java-lang/java_lang_VMSystem.c
+ (nanoTime, currentTimeMillis): Switch the former to native code and
+ the latter to java.
+
+2006-07-26 Andreas Tobler <a.tobler@schweiz.ch>
+
+ * gnu/java/awt/peer/qt/QtCheckboxPeer.java: Removed unneeded imports.
+ * gnu/java/awt/peer/qt/QtComponentGraphics.java: Likewise.
+ * gnu/java/awt/peer/qt/QtComponentPeer.java: Likewise.
+ * gnu/java/awt/peer/qt/QtContainerPeer.java: Likewise.
+ * gnu/java/awt/peer/qt/QtDialogPeer.java: Likewise.
+ * gnu/java/awt/peer/qt/QtEmbeddedWindowPeer.java: Likewise.
+ * gnu/java/awt/peer/qt/QtFontMetrics.java: Likewise.
+ * gnu/java/awt/peer/qt/QtFontPeer.java: Likewise.
+ * gnu/java/awt/peer/qt/QtGraphics.java: Likewise.
+ * gnu/java/awt/peer/qt/QtGraphicsEnvironment.java: Likewise.
+ * gnu/java/awt/peer/qt/QtImage.java: Likewise.
+ * gnu/java/awt/peer/qt/QtImageConsumer.java: Likewise.
+ * gnu/java/awt/peer/qt/QtImageDirectGraphics.java: Likewise.
+ * gnu/java/awt/peer/qt/QtImageGraphics.java: Likewise.
+ * gnu/java/awt/peer/qt/QtMenuBarPeer.java: Likewise.
+ * gnu/java/awt/peer/qt/QtMenuItemPeer.java: Likewise.
+ * gnu/java/awt/peer/qt/QtPopupMenuPeer.java: Likewise.
+ * gnu/java/awt/peer/qt/QtScreenDeviceConfiguration.java: Likewise.
+ * gnu/java/awt/peer/qt/QtScrollPanePeer.java: Likewise.
+ * gnu/java/awt/peer/qt/QtToolkit.java: Likewise.
+ * gnu/java/awt/peer/qt/QtVolatileImage.java: Likewise.
+
+2006-07-26 Roman Kennke <kennke@aicas.com>
+
+ * java/awt/KeyboardFocusManager.java
+ (getFocusOwner): Don't check permanent owner.
+ (getGlobalFocusOwner): Don't check permanent owner.
+
+2006-07-26 Carsten Neumann <cn-develop@gmx.net>
+
+ * StrictMath.java (cosh): New method.
+ (expm1): New method.
+ (EXPM1_Q1): New field.
+ (EXPM1_Q2): Likewise.
+ (EXPM1_Q3): Likewise.
+ (EXPM1_Q4): Likewise.
+ (EXPM1_Q6): Likewise.
+
+2006-07-26 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/basic/BasicButtonListener.java
+ (mousePressed): Request focus if appropriate.
+ * javax/swing/text/DefaultCaret.java
+ (mousePressed): Also handle the focus of the text component
+ as specified. Don't consume events.
+
+2006-07-26 Roman Kennke <kennke@aicas.com>
+
+ * gnu/java/awt/peer/gtk/GtkComponentPeer.java
+ (focusRequest): Removed field.
+ (postFocusEvent(int,boolean,Component)): Removed.
+ (postFocusEvent(int,boolean)): Reverted to post event using
+ the heavyweight component.
+ (requestFocus): Post focus event using the heavyweight
+ component.
+ * gnu/java/awt/peer/gtk/GtkWindowPeer.java
+ (requestFocus): Post focus event using the heavyweight
+ component.
+ * java/awt/AWTEvent.java
+ (isFocusManagerEvent): New field, indicating if this is
+ an event that is redispatched by the KeyboardFocusManager.
+ * java/awt/Component.java
+ (requestFocusImpl): Register component for
+ heavyweight->lightweight mapping.
+ (dispatchEventImpl): Retarget focus events before dispatching
+ to the KeyboardFocusManager. Use new AWTEvent flag instead
+ of locking hack. Dispatch all events through the
+ KeyboardFocusManager. Don't request focus on lightweight
+ components.
+ * java/awt/DefaultKeyboardFocusManager.java
+ (dispatchEvent): Pulled out handling of FOCUS_GAINED and
+ FOCUS_LOST.
+ (handleFocusGained): Fixed handling of temporary vs permanent
+ focus changes. Added some checks.
+ (handleFocusLost): Fixed handling of temporary vs permanent
+ focus changes. Added some checks.
+ * java/awt/EventDispatchThread.java
+ (run): Don't dispatch to KeyboardFocusManager here. This
+ is done in Component.dispatchEventImpl().
+ * java/awt/KeyboardFocusManager.java
+ (redispatchEvent): Use new AWTEvent flag instead of locking hack.
+ (focusRequests): New field.
+ (retargetFocusEvent): New method. Retargets focus events
+ that come from heavyweights to the correct lightweight component.
+ (addLightweightFocusRequest): New method. Stores a mapping
+ for later retargetting of heavyweight focus events.
+ * java/awt/Window.java
+ (addFocusListener): Removed bogus method. If at all, this
+ should be performed in the KeyboardFocusManager.
+ (Window): Don't install a focus listener on the Window.
+
+2006-07-26 Robert Schuster <robertschuster@fsfe.org>
+
+ * gnu/java/awt/peer/gtk/CairoGraphics2D.java:
+ (drawLine): Apply shift to line coordinates.
+
+2006-07-26 Robert Schuster <robertschuster@fsfe.org>
+
+ * java/awt/image/ColorConvertOp.java: Fixed copyright header.
+ (copyimage): Do not call setRenderingHints() when the respective map
+ does not exist.
+ (filter): Removed code to clone the ColorModel instance.
+ * java/awt/image/ColorModel.java:
+ (cloneColorModel): Removed.
+
+2006-07-26 Robert Schuster <robertschuster@fsfe.org>
+
+ * javax/swing/JTabbedPane.java:
+ (setSelectedIndex): Removed updating of component visibility status,
+ added note.
+ (remove(Component)): Use indexOfComponent() to find whether we have
+ to use super.remove(int) or removeTabAt().
+
+2006-07-26 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/JOptionPane.java
+ (createDialog): Add property change handler for closing
+ the dialog when the value property changes.
+ (ValuePropertyHandler): New inner helper class.
+ * javax/swing/plaf/basic/BasicOptionPaneUI.java
+ (OptionPaneCloseAction): New class.
+ (messageForeground): Removed field.
+ (messageBorder): Removed field.
+ (buttonBorder): Removed field.
+ (addIcon): Configure the new label.
+ (addMessageComponents): Configure newly created labels.
+ (burstStringInto): Likewise.
+ (createButtonArea): Install border here.
+ (createMessageArea): Install border and foreground here.
+ (createSeparator): Added comment and removed
+ NotImplementedException.
+ (installComponents): Don't install the UI defaults for the
+ message and button area here. This is moved to the
+ corresponding create* methods. Adjusted comment about
+ separator.
+ (installDefaults): Removed initialization of removed fields.
+ (installKeyboardActions): Implemented.
+ (getActionMap): New helper method.
+ (createDefaultActions): New helper method.
+ (uninstallDefaults): Removed de-initialization of removed fields.
+ (uninstallKeyboardActions): Implemented.
+ (configureLabel): New helper method.
+ * javax/swing/plaf/basic/BasicTableUI.java
+ (getActionMap): Fixed the UI property names.
+ * javax/swing/plaf/basic/BasicToolBarUI.java
+ (getActionMap): Fixed the UI property names.
+
+2006-07-26 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/BandedSampleModel.java
+ (getDataElements): Check for negative x or y,
+ (getPixels): Likewise,
+ (getSamples): Likewise,
+ (setSamples): Likewise.
+
+2006-07-26 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/basic/BasicToolBarUI.java
+ (ToolBarAction): New inner class for handling keyboard
+ actions.
+ (installKeyboardActions): Implemented.
+ (getActionMap): New helper method.
+ (createDefaultActions): New helper method.
+ (installListeners): Install focus listener on toolbar's
+ children, rather than the toolbar itself.
+ (navigateFocusedComp): Implemented.
+ (uninstallKeyboardActions): Implemented.
+ (uninstallListeners): Uninstall focus listener from
+ toolbar's children, rather than the toolbar itself.
+ (ToolBarContListener.componentAdded): Install focus
+ listener on added child.
+ (ToolBarContListener.componentRemoved): Uninstall focus
+ listener from removed child.
+ (ToolBarFocusListener.ToolBarFocusListener): Nothing to do here.
+ (ToolBarFocusListener.focusGained): Implemented.
+ (ToolBarFocusListener.focusLost): Implemented.
+
+2006-07-26 Roman Kennke <kennke@aicas.com>
+
+ * java/awt/DefaultKeyboardFocusManager.java
+ (dispatchEvent): Notify old focus owner when it has lost
+ focus.
+
+2006-07-26 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/basic/BasicTableUI.java
+ (FocusHandler.focusGained): Implemented to refresh the
+ lead cell.
+ (FocusHandler.focusLost): Implemented to refresh the
+ lead cell.
+ (FocusHandler.repaintLeadCell): New helper method.
+ (MouseInputHandler.mouseEntered): Do nothing here.
+ (MouseInputHandler.mouseExited): Do nothing here.
+ (MouseInputHandler.mouseMoved): Do nothing here.
+ (installKeyboardActions): Rewritten to use a shared InputMap
+ and ActionMap and correctly install the maps via SwingUtilities
+ methods.
+ (getActionMap): New helper method.
+ (createDefaultActions): New helper method.
+ (ActionListenerProxy): Removed unneeded class.
+ (TableAction): Made class static.
+ (TableAction.actionPerformed): Determine table by fetching
+ the event source. Pass the table to helper methods.
+ Use __command__ hack to determine the action command.
+ (TableAction.getFirstVisibleColumnIndex): Get table as argument.
+ (TableAction.getLastVisibleColumnIndex): Get table as argument.
+ (TableAction.getFirstVisibleRowIndex): Get table as argument.
+ (TableAction.getLastVisibleRowIndex): Get table as argument.
+ (TableAction.advanceMultipleSelection): Get table as argument.
+ (uninstallDefaults): Do nothing here.
+ (uninstallKeyboardActions): Uninstall the keyboard actions.
+
+2006-07-26 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/JComponent.java
+ (processKeyBinding): Store the action command as property
+ in the Action instance that we call. This allows for
+ improvement on the side of the Action.
+
+2006-07-26 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/metal/MetalUtils.java
+ (fillMetalPattern): Use fillRect() instead of drawLine() to
+ fill single pixels.
+
+2006-07-26 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/GapContent.java
+ (getChars): Check for negative length and throw
+ BadLocationException.
+
+2006-07-26 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/basic/BasicMenuBarUI.java
+ (FocusAction): Made class static.
+
+2006-07-26 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/basic/BasicLookAndFeel.java
+ (initComponentDefaults): Add keyboard bindings for
+ PopupMenu.
+
+2006-07-26 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/UIManager.java
+ (getLookAndFeelDefaults): Return the look and feel defaults.
+ (setLookAndFeel): Improved exception messsage.
+
+2006-07-26 David Gilbert <david.gilbert@object-refinery.com>
+
+ * javax/swing/text/StringContent.java
+ (StringContent): Changed initialLength to 10.
+
+2006-07-26 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/util/Vector.java: Fixed API doc typo.
+
+2006-07-26 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/BandedSampleModel.java
+ (createCompatibleSampleModel): Fixed typo in loop increment, set
+ correct scanlineStride, and updated API docs.
+
+2006-07-25 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/basic/BasicPopupMenuUI.java
+ (NavigateAction): New inner class. This is responsible for
+ keyboard navigation through menus.
+ (KeyboardHelper): New inner class. This manages the
+ keyboard mappings and focus when a popup opens or closes.
+ (keyboardHelper): New static field.
+ (numPopups): New static field.
+ (installUI): Create KeyboardHelper for first popup.
+ Call installKeyboardActions().
+ (installKeyboardActions): Removed NotImplementedException.
+ This method is a no-op.
+ (installKeyboardActionsImpl): New method. Installs keyboard
+ mapping when a popup is opened.
+ (getActionMap): New helper method.
+ (createDefaultActions): New helper method.
+ (uninstallUI): Uninstall KeyboardHelper when last Popup is
+ uninstalled. Call uninstallKeyboardActions().
+ (uninstallKeyboardActions): Removed NotImplementedException.
+ This method is a no-op.
+ (uninstallKeyboardActionsImpl): New method. Uninstalls keyboard
+ mapping when a popup is closed.
+
+2006-07-25 Roman Kennke <kennke@aicas.com>
+
+ * java/awt/Component.java
+ (requestFocus()): Reimplemented to use requestFocusImpl().
+ (requestFocus(boolean)): Reimplemented to use requestFocusImpl().
+ (requestFocusInWindow()): Reimplemented to use requestFocusImpl().
+ (requestFocusInWindow(boolean)): Reimplemented to use
+ requestFocusImpl().
+ (requestFocusImpl): Reimplemented focus request to use
+ new peer method. Also added some obvious additional checks
+ for rejecting focus requests early.
+ * java/awt/ComponentPeer.java
+ (requestFocus(Component,boolean,boolean,long)): Documented
+ this method.
+ * gnu/java/awt/peer/gtk/GtkComponentPeer.java
+ (requestFocus): New field.
+ (gtkWidgetHasFocus): New native method.
+ (gtkWidgetCanFocus): New native method.
+ (requestFocus): Replaced with assert false to prevent
+ usage of obsolete method.
+ (postFocusEvent(int,boolean,Component)): New overloaded method
+ for posting the focus event to a specific target.
+ (postFocusEvent(int,boolean)): Post event to requestFocus
+ component.
+ (requestFocus(Component,boolean,boolean,long)): Implemented.
+ (getWindowFor): New helper method.
+ (isLightweightDescendant): New helper method.
+ * gnu/java/awt/peer/gtk/GtkWindowPeer.java
+ (gtkWindowHasFocus): New native method.
+ (requestFocus(Component,boolean,boolean,long)): New method.
+ Overrides GtkComponentPeer method to specially handly the
+ case when a Window receives a focus request for a lightweight
+ child.
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
+ (gtkWidgetHasFocus): New native method.
+ (gtkWidgetCanFocus): New native method.
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
+ (gtkWindowHasFocus): New native method.
+ * include/gnu_java_awt_peer_gtk_GtkComponentPeer.h,
+ * include/gnu_java_awt_peer_gtk_GtkWindowPeer.h:
+ Regenerated.
+
+2006-07-25 Francis Kung <fkung@redhat.com>
+
+ * java/awt/DefaultKeyboardFocusManager.java
+ (dispatchEvent): Add check for valid component.
+
+2006-07-25 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/MBeanConstructorInfo.java:
+ New file.
+ * javax/management/MBeanNotificationInfo.java:
+ Documentation fix.
+ * javax/management/MBeanParameterInfo.java:
+ New file.
+
+2006-07-25 Robert Schuster <robertschuster@fsfe.org>
+
+ * java/awt/peer/gtk/CairoGraphics.java:
+ (drawLine): Added special case for 1 pixel lines.
+
+2006-07-25 Robert Schuster <robertschuster@fsfe.org>
+
+ Fixes PR27844.
+ * java/awt/peer/gtk/CairoGraphics.java:
+ (drawLine): Removed calls to shifted().
+
+2006-07-25 Robert Schuster <robertschuster@fsfe.org>
+
+ * javax/swing/JTabbedPane.java:
+ (remove(Component)): Rewritten.
+ (setSelectedIndex): Implemented updating of component visibility state.
+
+2006-07-25 Sven de Marothy <sven@physto.se>
+
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkVolatileImage.c
+ (init): Default to the actual depth in the worst case.
+
+ * java/awt/Font.java
+ (createFont(int, File)): New method.
+
+2006-07-25 Ito Kazumitsu <kaz@maczuka.gcd.org>
+
+ Fixes bug #28413
+ * gnu/java/util/regex/RETokenEnd.java(check_java_line_terminators):
+ New field.
+ (RETokenEnd): New constructer to set check_java_line_terminators.
+ (matchThis): Checck line terminators if check_java_line_terminators.
+ * gnu/java/util/regex/RETokenStart.java: Likewise.
+ * gnu/regexp/RE.java(initialize): Use the new constructors for
+ RETokenEnd and RETokenStart if REG_MULTILINE is set.
+ * java/util/regex/Pattern.java(Patteren): Changed so that
+ gnu/regexp/RE.java may use the new the new constructors.
+
+2006-07-25 Roman Kennke <kennke@aicas.com>
+
+ * java/awt/Container.java
+ (focusTraversalPolicyProvider): New field.
+ (isFocusTraversalPolicyProvider): New method.
+ (setFocusTraversalPolicyProvider): New method.
+ * java/awt/ContainerOrderFocusTraversalPolicy.java
+ (getFirstComponent): Use accept() instead of lengthy checks.
+ Don't fetch getComponents() to avoid copying of array.
+ Traverse down the hierarchy to find the first focused component.
+ * java/awt/DefaultKeyboardFocusManager.java
+ (dispatchEvent): Let the initial component request focus.
+
+2006-07-25 David Gilbert <david.gilbert@object-refinery.com>
+
+ * javax/swing/text/Segment.java
+ (last): Update current index before returning DONE for zero count.
+
+2006-07-24 Mark Wielaard <mark@klomp.org>
+
+ * javax/swing/tree/TreePath.java (equals): Swap path equals call.
+
+2006-07-25 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/basic/BasicMenuBarUI.java
+ (FocusAction): New inner class. Used to grab focus.
+ (installKeyboardActions): Implemented.
+ (uninstallKeyboardActions): Implemented.
+ (getActionMap): New helper method.
+ (createDefaultActions): New helper method.
+
+2006-07-25 Robert Schuster <robertschuster@fsfe.org>
+
+ * examples/gnu/classpath/examples/swing/Demo.java:
+ (mkMenuBar): Install instantiable basic look and feel.
+ (InstantiableBasicLookAndFeel): New inner class.
+
+2006-07-25 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/basic/BasicInternalFrameUI.java
+ (GlassPaneDispatcher.dragTarget): New field.
+ (GlassPaneDispatcher.isDragging): New field.
+ (GlassPaneDispatcher.pressedComponent): Removed field.
+ (GlassPaneDispatcher.tempComponent): Removed field.
+ (GlassPaneDispatcher.pressCount): Removed field.
+ (GlassPaneDispatcher.mousePressed): Call
+ borderListener.mousePressed() to activate the frame.
+ (acquireComponentForMouseEvent): Removed method.
+ (handleEvent): Rewritten.
+ (redispatch): New method.
+ (InternalFramePropertyChangeListener.propertyChange):
+ Make glasspane invisible when frame is selected, and visible
+ if it gets deselected.
+
+2006-07-25 Roman Kennke <kennke@aicas.com>
+
+ * java/awt/LightweightDispatcher.java
+ (handleMouseEvent): Dispatch event to real target if
+ the dragTarget has become invisible in the meantime.
+
+2006-07-25 David Gilbert <david.gilbert@object-refinery.com>
+
+ * javax/swing/text/TabSet.java
+ (equals): New method override for 1.5,
+ (hashCode): Likewise,
+ (toString): Added spaces to match reference implementation.
+
+2006-07-24 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/IntrospectionException.java,
+ * javax/management/MBeanAttributeInfo.java:
+ New files.
+ * javax/management/MBeanNotificationInfo.java:
+ Documentation cleanups.
+
+2006-07-24 David Gilbert <david.gilbert@object-refinery.com>
+
+ * javax/swing/text/TabSet.java
+ (TabSet): Check for null argument,
+ (getTab): Throw IllegalArgumentException for index out of bounds,
+ (getTabIndexAfter): Changed test to '<=',
+ and updated API docs all over,
+ * javax/swing/text/TabStop.java: Updated API docs.
+
+2006-07-24 David Gilbert <david.gilbert@object-refinery.com>
+
+ * javax/swing/text/TabStop.java
+ (toString): Don't use 'left ' prefix, and added space between tab
+ location and '(w/leader)' suffix.
+
+2006-07-24 Francis Kung <fkung@redhat.com>
+
+ * javax/swing/JComboBox.java
+ (DefaultKeySelectionManager): Implemented.
+ (createDefaultKeySelectionManager): Implemented.
+ (getKeySelectionManager): Implemented.
+ (processKeyEvent): Removed duplicate code.
+ * javax/swing/JPopupMenu.java
+ (selectionModel): Changed visibility.
+ * javax/swing/plaf/basic/BasicComboBoxUI.java
+ (KeyHandler.keyPressed): Added navigation keys.
+ (configureEditor): Add key listener.
+ (installListeners): Install focus listener to combo box.
+ (isNavigationKey): Added enter, escape, and tab.
+ (selectPreviousPossibleValue): Added out of bounds check.
+ (unconfigureEditor): Remove key listener.
+ * javax/swing/plaf/metal/MetalComboBoxButton.java
+ (paintComponent): Highlight combo box when in focus.
+
+2006-07-24 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/SwingUtilities.java
+ (isLeftMouseButton): Fixed condition.
+ * java/awt/LightweightDispatcher.java
+ (handleMouseEvent): Dispatch MOUSE_ENTERED even when mouse
+ is dragged.
+
+2006-07-24 Roman Kennke <kennke@aicas.com>
+
+ * gnu/java/awt/peer/gtk/CairoGraphics2D.java
+ (setPaint): Fixed scaleX and scaleY.
+
+2006-07-24 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/JTable.java
+ (handleInsert): Repaint the whole table for variable row
+ height tables and an optimized region otherwise.
+ (handleDelete): Likewise.
+ (handleUpdate): Likewise.
+
+2006-07-24 Mario Torre <neugens@limasoftware.net>
+
+ * gnu/java/awt/peer/gtk/GtkToolkit.java (createDragGestureRecognizer):
+ now explicity registerListeners on GtkMouseDragGestureRecognizer
+ instance.
+ * gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java
+ (unregisterListeners): new method, overrided from base class
+ to rise visibility (from protected to public).
+ (registerListeners): Likewise.
+ (GtkMouseDragGestureRecognizer): fixed potential threading issue:
+ removed call to registerListeners from the constructor.
+
+2006-07-23 Mark Wielaard <mark@klomp.org>
+
+ * configure.ac: Check for moc and moc-qt4.
+
+2006-07-23 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/Kernel.java: API doc updates.
+
+2006-07-22 Andreas Tobler <a.tobler@schweiz.ch>
+
+ * gnu/java/awt/peer/gtk/CairoSurface.java: Optimize pixel swap code a
+ bit more.
+
+2006-07-22 Mark Wielaard <mark@klomp.org>
+
+ * java/lang/Iterable.java: Import all of java.util.
+ * lib/mkcollections.pl.in (javautilclasses): Add Iterable.
+ * lib/Makefile.am: Only search for .java files in COLLECTIONS_PREFIX.
+
+2006-07-22 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * doc/vmintegration.texinfo:
+ Document getType(String).
+ * gnu/java/lang/management/MemoryPoolMXBeanImpl.java,
+ * java/lang/management/MemoryPoolMXBean.java:
+ (getType()): Implemented.
+ * vm/reference/gnu/java/lang/management/VMMemoryPoolMXBeanImpl.java
+ (getType(String)): Implemented.
+
+2006-07-22 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * doc/vmintegration.texinfo:
+ Move end of itemization block.
+
+2006-07-22 Robert Schuster <robertschuster@fsfe.org>
+
+ * javax/swing/plaf/metal/MetalLookAndFeel.java:
+ (initComponentDefaults): Added new properties, added comments.
+
+2006-07-22 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * doc/vmintegration.texinfo:
+ Mention callback methods.
+ * gnu/java/lang/management/MemoryMXBeanImpl.java:
+ (fireNotification(String,String,long,long,long,long,long)):
+ Made package-private.
+ (fireThresholdExceededNotification(String,long,long,long,
+ long,long)): Likewise.
+ (fireCollectionThresholdExceededNotification(String,long,
+ long,long,long,long)): Likewise.
+ * java/lang/management/MemoryMXBean.java:
+ Document notifications.
+
+2006-07-22 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * gnu/java/lang/management/MemoryMXBeanImpl.java:
+ (fireNotification(String,String,long,long,long,long,long)):
+ Implemented.
+ (fireThresholdExceededNotification(String,long,long,long,
+ long,long)): Likewise.
+ (fireCollectionThresholdExceededNotification(String,long,
+ long,long,long,long)): Likewise.
+ * java/lang/management/MemoryNotificationInfo.java:
+ Use composite type from MemoryMXBeanImpl.
+ * javax/management/openmbean/CompositeData.java:
+ Correct documentation.
+ * javax/management/openmbean/CompositeDataSupport.java,
+ * javax/management/openmbean/InvalidKeyException.java:
+ New files.
+
+2006-07-22 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * gnu/java/security/util/IntegerUtil.java: New file.
+
+2006-07-22 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ PR Classpath/28100
+ * gnu/javax/crypto/cipher/TripleDES.java: Updated documentation.
+ (KEY_SIZE): Likewise.
+ (adjustParity(int,byte[],int): New method.
+ (adjustParity(byte[],int): Call above method with 3 as 1st argument.
+ (isParityAdjusted(int,byte[],int)): New method.
+ (isParityAdjusted): Call above method with 3 as 1st argument.
+ (keySizes): Add 8 and 16 as other valid key sizes.
+ (makeKey): Amended to cater for 1, 2 and 3 independent DES keys.
+
+2006-07-22 Andreas Tobler <a.tobler@schweiz.ch>
+
+ * gnu/java/awt/peer/gtk/CairoSurface.java (CairoSurface): Rearrange
+ code for the pixel swap routine to be more efficient.
+
+2006-07-20 Lillian Angel <langel@redhat.com>
+
+ * gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java:
+ Removed unused fields.
+ (GtkMouseDragGestureRecognizer): Removed initializations.
+
+2006-07-20 Lillian Angel <langel@redhat.com>
+
+ * gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java
+ (GtkMouseDragGestureRecognizer): New constructor.
+ (GtkMouseDragGestureRecognizer): New constructor.
+ (GtkMouseDragGestureRecognizer): New constructor.
+ (mouseClicked): Removed FIXME.
+ (mousePressed): Implemented.
+ (mouseReleased): Implemented.
+ (mouseEntered): Implemented.
+ (mouseDragged): Implemented to check mouse point and trigger origin.
+ (mouseMoved): Removed FIXME.
+ (getDropActionFromEvent): New helper function used to convert mouse event
+ modifiers to a drop action.
+ * java/awt/dnd/DragSource.java
+ (getDragThreshold): Changed to return some arbitrary value for testing
+ purposes.
+
+2006-07-20 Roman Kennke <kennke@aicas.com>
+
+ * java/awt/LightweightDispatcher.java
+ (findTarget): Also consider components that have their eventMask
+ set, for compatibility with stonage AWT. Optimized check
+ for MouseListener.
+ (handleMouseEvent): Likewise.
+
+2006-07-20 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/JTable.java
+ (tableChanged): Split out handling of the event into multiple
+ subroutines.
+ (handleCompleteChange): New method. Clear the selection and
+ check the lead/anchor indices.
+ (handleInsert): New method. Check the lead/anchor indices.
+ Optimized repainting.
+ (handleDelete): New method. Check the lead/anchor indices.
+ Optimized repainting.
+ (handleUpdate): New method. Optimized repainting.
+ (checkSelection): New helper method.
+ (setSelectionModel): Update lead/anchor indices.
+
+2006-07-20 Lillian Angel <langel@redhat.com>
+
+ PR 28440
+ * gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
+ (dispose): Reset all fields.
+
+2006-07-20 Roman Kennke <kennke@aicas.com>
+
+ * gnu/java/awt/peer/x/XToolkit.java
+ (createImage(InputStream)): Only copy image to Pixmap if
+ it's actually opaque. Transparent images are left as
+ BufferedImage and composited later onto the screen.
+ * gnu/java/awt/peer/x/XGraphics.java
+ (XGraphics): Fetch some parameters for image rendering.
+ (drawImage): Added special handling of transparent images.
+ (getRGB): New helper method.
+ (setRGB): New helper method.
+
+2006-07-20 Roman Kennke <kennke@aicas.com>
+
+ * gnu/javax/imageio/IIOInputStream.java: New class. Wraps
+ ImageInputStreams as normal InputStreams.
+ * gnu/javax/imageio/gif/GIFStream.java:
+ Moved to gnu/javax/imageio/IIOInputStream.java.
+ * gnu/javax/imageio/gif/GIFImageReader.java
+ (readImage): Use IIOInputStream.
+ * gnu/javax/imageio/gif/GIFImageReaderSpi.java
+ (canDecodeInput): Use IIOInputStream.
+ * gnu/javax/imageio/png/PNGException.java: Make subclass
+ of IOException.
+ * gnu/javax/imageio/png/PNGImageReader.java: New class.
+ Implements the ImageIO ImageReader for PNG.
+ * gnu/javax/imageio/png/PNGImageReaderSpi.java: New class.
+ Implements the ImageIO ImageReaderSpi for PNG.
+ * javax/imageio/spi/IIORegistry.java:
+ (IIORegistry): Add PNGImageReaderSpi.
+
+2006-07-20 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/ComponentSampleModel.java
+ (getPixel): Added argument check,
+ (getSample): Modified exception message.
+
+2006-07-20 David Gilbert <david.gilbert@object-refinery.com>
+
+ PR Classpath/28422
+ * java/awt/image/ConvolveOp.java
+ (filter(Raster, WritableRaster)): Reimplemented,
+ (fillEdge): New private method.
+
+2006-07-19 Keith Seitz <keiths@redhat.com>
+
+ * include/jvmti.h (JVMTI_VERSION_1_0): Define.
+ (JVMTI_VERSION): Define.
+
+2006-07-19 Roman Kennke <kennke@aicas.com>
+
+ * resource/gnu/regexp/MessagesBundle.properties,
+ * resource/gnu/regexp/MessagesBundle_fr.properties,
+ * resource/gnu/regexp/MessagesBundle_it.properties:
+ Moved to resource/gnu/java/util/regex.
+ * resource/gnu/java/util/regex/MessagesBundle.properties,
+ * resource/gnu/java/util/regex/MessagesBundle_fr.properties,
+ * resource/gnu/java/util/regex/MessagesBundle_it.properties:
+ New files.
+ * gnu/java/util/regex/RE.java
+ Use new resource bundle location.
+
+2006-07-19 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/JComponent.java
+ (paintChildren): Refactored. The paintChildrenOptimized method
+ has been moved back in here. Added locking of the tree and
+ only check for completely obscured child components
+ when not optimized drawing enabled. Use Graphics.create() to
+ protect from irreversible changes.
+ (isCompletelyObscured): New helper method.
+ (paintComponent): Also use Graphics.create() for Graphics2D,
+ to protect from irreverible changes.
+ (clipAndTranslateGraphics): Refactored to use more efficient
+ iterative (vs recursive) approach.
+ * javax/swing/RepaintManager.java
+ (getOffscreenBuffer): Create image from root component.
+
+2006-07-19 Roman Kennke <kennke@aicas.com>
+
+ * gnu/java/awt/peer/x/XGraphics.java
+ (translate): Don't set the clip on the X server.
+ (clipRect): Use setXClip() to set the clip on the X server.
+ (hitClip): More efficient and correct implementation.
+ (setClip): Use setXClip() to set the clip on the X server.
+ (setClip(Shape)): Use setXClip() to set the clip on the X server.
+ (copyArea): Translate and clip the source rectangle correctly.
+ (dispose): Only flush when object is not yet disposed.
+ (clone): Use setXClip() to set the clip on the X server.
+
+2006-07-19 Sven de Marothy <sven@physto.se>
+
+ * gnu/javax/imageio/png/PNGChunk.java,
+ * gnu/javax/imageio/png/PNGData.java,
+ * gnu/javax/imageio/png/PNGDecoder.java,
+ * gnu/javax/imageio/png/PNGEncoder.java,
+ * gnu/javax/imageio/png/PNGException.java,
+ * gnu/javax/imageio/png/PNGFile.java,
+ * gnu/javax/imageio/png/PNGFilter.java,
+ * gnu/javax/imageio/png/PNGGamma.java,
+ * gnu/javax/imageio/png/PNGHeader.java,
+ * gnu/javax/imageio/png/PNGICCProfile.java,
+ * gnu/javax/imageio/png/PNGPalette.java,
+ * gnu/javax/imageio/png/PNGPhys.java,
+ * gnu/javax/imageio/png/PNGTime.java:
+ New files.
+
+2006-07-19 Sven de Marothy <sven@physto.se>
+
+ * java/net/Inet6Address.java:
+ (getScopedId, getScopedInterface): New methods.
+
+2006-07-19 Lillian Angel <langel@redhat.com>
+
+ * examples/gnu/classpath/examples/awt/Demo.java
+ (DragDropWindow): Fixed typo in Label text.
+ * gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java
+ (GtkDragSourceContextPeer): Removed unneeded initialization for field.
+ (startDrag): Initialized context field.
+ (transferablesFlavorsChanged): Removed FIXME. Nothing is done in this
+ function.
+ (dragEnter): New function.
+ (dragExit): Likewise.
+ (dragDropEnd): Likewise.
+ (dragMouseMoved): Likewise.
+ (dragOver): Likewise.
+ (dragActionChanged): Likewise.
+
+2006-07-19 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ PR Classpath/26302
+ * resource/java/security/classpath.security: Updated copyright year.
+ (auth.login.defaultCallbackHandler): New property; set to our default
+ callback handler. This is needed by the LoginContext when no callback
+ handler was specified.
+ * javax/security/auth/login/LoginContext.java: Updated copyright year.
+ (LoginContext(4)): Assign passed parameters to local fields before invoking
+ lookup method.
+
+2006-07-19 Roman Kennke <kennke@aicas.com>
+
+ * gnu/java/awt/peer/x/XGraphics.java
+ (drawImage(Image,int,int,int,int,int,int,int,int,ImageObserver)):
+ Fixed ordering of parameters.
+
+2006-07-18 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * gnu/java/lang/management/MemoryMXBeanImpl.java:
+ (MemoryMXBeanImpl()): Implemented.
+ (ListenerData): New private class.
+ (addNotificationListener(NotificationListener,
+ NotificationFilter, Object)): Implemented.
+ (getNotificationInfo()): Likewise.
+ (removeNotificationListener(NotificationListener)):
+ Likewise.
+ (removeNotificationListener(NotificationListener,
+ NotificationFilter, Object)): Likewise.
+
+2006-07-18 Roman Kennke <kennke@aicas.com>
+
+ * gnu/java/awt/peer/x/XFontPeer.java
+ (encodeFont): Be more flexible with font sizes.
+ (validSize): New helper method.
+ * gnu/java/awt/peer/x/XGraphics.java
+ (drawImage(Image,int,int,int,int,int,int,int,int,ImageObserver)):
+ Implemented.
+ (drawImage(Image,int,int,int,int,int,int,int,int,Color,ImageObserver)):
+ Implemented.
+ * gnu/java/awt/peer/x/XImage.java
+ (properties): New field.
+ (getProperty): Implemented.
+ * resource/gnu/java/awt/peer/x/fonts.properties:
+ Added copyright header. Fixed font size field.
+
+2006-07-18 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/BandedSampleModel.java
+ (createDataBuffer): New method override,
+ * java/awt/image/ByteLookupTable.java
+ (ByteLookupTable(int, byte[][])): Create new array to hold references,
+ (ByteLookuptable(int, byte[])): Check for null array,
+ * java/awt/image/ComponentSampleModel.java
+ (createDataBuffer): Removed unnecessary braces,
+ (getSample): Check (x, y) is within bounds,
+ * java/awt/image/ShortLookupTable.java
+ (ShortLookupTable(int, short[][])): Create new array to hold references,
+ (ShortLookupTable(int, short[])): Check for null array,
+ (getTable): Added API docs,
+ (lookupPixel): Source reformatting.
+
+2006-07-18 Tania Bento <tbento@redhat.com>
+
+ * java/awt/GridLayout.java
+ (setHgap): Illegal Argument Exception should not be thrown if
+ hgap < 0.
+ (setVgap): Illegal Argument Exception should not be thrown if
+ vgap < 0.
+ (toString): Opening square braket ([) should appear before hgap
+ value, not the name of the class.
+
+2006-07-18 Roman Kennke <kennke@aicas.com>
+
+ * lib/copy-vmresources.sh.in: Reverted.
+ * gnu/java/awt/peer/x/fonts.properties: Moved to resource/
+ * resource/gnu/java/awt/peer/x/fonts.properties: New file.
+
+2006-07-18 Roman Kennke <kennke@aicas.com>
+
+ * lib/copy-vmresources.sh.in: Include properties from X peers.
+
+2006-07-18 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ PR Classpath/27205
+ * tools/gnu/classpath/tools/jarsigner/SFHelper.java (writeDSA): Check
+ certificate validity.
+ (getIssuerName): New method.
+ (getSubjectName): Likewise.
+ (getNotAfterDate): Likewise.
+ (getNotBeforeDate): Likewise.
+ * resource/gnu/classpath/tools/jarsigner/messages.properties: Added
+ messages for newly added messages in SFHelper.
+
+2006-07-18 Roman Kennke <kennke@aicas.com>
+
+ * gnu/java/awt/peer/x/XDialogPeer.java: New class.
+ * gnu/java/awt/peer/x/XEventPump.java
+ (handleEvent): Cast to XWindowPeer rather than XFramePeer.
+ * gnu/java/awt/peer/x/XFramePeer.java
+ Made a subclass of XWindowPeer, rather than SwingFramePeer.
+ * gnu/java/awt/peer/x/XGraphics.java
+ Made subclass of Graphics rather than Graphics2D. Removed
+ all Graphics2D specific method stubs.
+ (setColor): Map colors using the X color map that is
+ stored in XToolkit.
+ * gnu/java/awt/peer/x/XToolkit.java
+ (colorMap): New field.
+ (getLocalGraphicsEnvironment): Return new XGraphicsEnvironment
+ instance.
+ (createDialog): Implemented.
+ (createImage(ImageProducer)): Implemented.
+ (createImage(InputStream)): Use createImage(ImageProducer)
+ to convert the BufferedImage to an XImage.
+ * gnu/java/awt/peer/x/XWindowPeer.java
+ (XWindowPeer): Removed debug output.
+
+2006-07-18 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/BufferedImageOp.java: API docs added,
+ * java/awt/image/RasterOp.java: Likewise.
+
+2006-07-18 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/Graphics2D.java: API docs updated.
+
+2006-07-18 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/WritableRaster.java: Added API docs and reformatted
+ source code.
+
+2006-07-18 Sven de Marothy <sven@physto.se>
+
+ * java/net/Inet6Address.java:
+ Add 1.5 serialized fields.
+ (getByAddress): New methods.
+ (readObject, writeObject): New methods.
+ (equals): Reimplement.
+
+2006-07-18 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/Raster.java: Added API docs and reformatted source
+ code.
+
+2006-07-18 Andreas Tobler <a.tobler@schweiz.ch>
+
+ * gnu/java/awt/peer/gtk/BufferedImageGraphics.java: Remove unneeded
+ imports.
+ * gnu/java/awt/peer/gtk/CairoSurface.java: Likewise.
+ * gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java: Likewise.
+ * gnu/java/awt/peer/gtk/ComponentGraphicsCopy.java: Likewise.
+ * gnu/java/awt/peer/gtk/GdkFontPeer.java: Likewise.
+ * gnu/java/awt/peer/gtk/GdkPixbufDecoder.java: Likewise.
+ * gnu/java/awt/peer/gtk/GtkButtonPeer.java: Likewise.
+ * gnu/java/awt/peer/gtk/GtkClipboardNotifier.java: Likewise.
+ * gnu/java/awt/peer/gtk/GtkComponentPeer.java: Likewise.
+ * gnu/java/awt/peer/gtk/GtkContainerPeer.java: Likewise.
+ * gnu/java/awt/peer/gtk/GtkDialogPeer.java: Likewise.
+ * gnu/java/awt/peer/gtk/GtkFramePeer.java: Likewise.
+ * gnu/java/awt/peer/gtk/GtkImage.java: Likewise.
+ * gnu/java/awt/peer/gtk/GtkImageConsumer.java: Likewise.
+ * gnu/java/awt/peer/gtk/GtkMenuBarPeer.java: Likewise.
+ * gnu/java/awt/peer/gtk/GtkMenuItemPeer.java: Likewise.
+ * gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java: Likewise.
+ * gnu/java/awt/peer/gtk/GtkPanelPeer.java: Likewise.
+ * gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java: Likewise.
+ * gnu/java/awt/peer/gtk/GtkScrollbarPeer.java: Likewise.
+ * gnu/java/awt/peer/gtk/GtkWindowPeer.java: Likewise.
+ * gnu/java/awt/peer/gtk/VolatileImageGraphics.java: Likewise.
+
+2006-07-17 Andreas Tobler <a.tobler@schweiz.ch>
+
+ * javax/swing/text/html/HTMLEditorKit.java: Rearrange import statements
+ to make it compile again under jikes. Note added.
+
+2006-07-17 Lillian Angel <langel@redhat.com>
+
+ * examples/gnu/classpath/examples/awt/Demo.java
+ (Demo): Added new window for DnD demo.
+ (DragDropWindow): New class.
+ * gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java:
+ Added new fields and declarations for native functions.
+ (GtkDragSourceContextPeer): Implemented.
+ (getComponentPeer): New function.
+ (startDrag): Partially implemented.
+ (getCursor): Implemented.
+ (setCursor): Implemented.
+ * include/GtkDragSourceContextPeer.h: New file.
+ * include/Makefile.am: Added new header file.
+ * java/awt/Component.java
+ (addNotify): Added call to the dropTarget's addNotify.
+ * java/awt/dnd/DragSource.java
+ (startDrag): Fixed code to use shared instances of peer and
+ context.
+ (getDragThreshold): Added stub.
+ * java/awt/dnd/DropTarget.java
+ (DropTarget): Implemented fully.
+ (addNotify): Added code to get the peer of the parent that is
+ not lightweight.
+ * java/awt/dnd/DropTargetDragEvent.java
+ (getTransferable): Added stub.
+ * native/jni/gtk-peer/GtkDragSourceContextPeer.c: New file.
+ * native/jni/gtk-peer/Makefile.am: Added new c file.
+ * gnu/java/awt/dnd/peer/gtk/GtkDropTargetContextPeer.java:
+ Changed to extend GtkGenericPeer.
+ (GtkDropTargetContextPeer): New constructor.
+ * gnu/java/awt/dnd/peer/gtk/GtkDropTargetPeer.java:
+ Changed to extend GtkGenericPeer.
+ (GtkDropTargetContextPeer): New constructor.
+
+2006-07-17 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/SinglePixelPackedSampleModel.java
+ (createSubsetSampleModel): Added argument check and API docs.
+
+2006-07-17 Roman Kennke <kennke@aicas.com>
+
+ * gnu/java/awt/peer/x/XGraphics.java
+ (copyArea): Implemented.
+
+2006-07-17 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/SinglePixelPackedSampleModel.java
+ (getSampleSize): Return copy of array,
+ (getOffset): Added API docs,
+ (getScanlineStride): Likewise,
+ (hashCode): Implemented.
+
+2006-07-17 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/MultiPixelPackedSampleModel.java
+ (getOffset): Updated API docs and source reformatting,
+ (getBitOffset): Source reformatting only,
+ (getDataElements): Likewise,
+ (getPixel): Likewise,
+ (getPixels): Removed method override,
+ (setDataElements): Reimplemented.
+
+2006-07-17 Gary Benson <gbenson@redhat.com>
+
+ * resource/META-INF/services/.cvsignore: New file.
+ * lib/.cvsignore: Updated.
+
+2006-07-17 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/plaf/basic/BasicButtonListener.java
+ (propertyChange): Only do the text layout caching as long
+ as the noGraphics2D property isn't set.
+ * javax/swing/plaf/basic/BasicMenuItemUI.java
+ (PropertyChangeHandler.propertyChange): Only do the text layout
+ caching as long as the noGraphics2D property isn't set.
+
+2006-07-17 Roman Kennke <kennke@aicas.com>
+
+ * gnu/java/awt/peer/x/XGraphicsEnvironment.java
+ (XGraphicsEnvironment): Make constructor public so that it
+ can be called via Class.forName().newInstance().
+ * gnu/java/awt/peer/x/XImage.java
+ (XImage): Fetch GraphicsEnvironment via
+ GraphicsEnvironment.getLocalGraphicsEnvironment() rather
+ than the XToolkit method, to avoid double instantiation
+ of the XGraphicsEnvironment.
+ * gnu/java/awt/peer/x/XToolkit.java
+ (env): Removed field.
+ (getLocalGraphicsEnvironment): Removed impl. This method
+ should not be called since we set the graphicsenv property
+ in the constructor.
+
+2006-07-16 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/util/UUID.java:
+ (compareTo(Object)): Call compareTo(UUID).
+ (compareTo(UUID)): Implemented.
+
+2006-07-16 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/StrictMath.java (cbrt): Added '@since'.
+
+2006-07-16 Carsten Neumann <cn-develop@gmx.net>
+
+ * java/lang/StrictMath.java (cbrt): New method.
+ (getLowDWord): New helper method.
+ (getHighDWord): Likewise.
+ (buildDouble): Likewise.
+ (CBRT_B1): New field.
+ (CBRT_B2): Likewise.
+ (CBRT_C): Likewise.
+ (CBRT_D): Likewise.
+ (CBRT_E): Likewise.
+ (CBRT_F): Likewise.
+ (CBRT_G): Likewise.
+
+2006-07-16 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/MBeanInfo.java:
+ (getNotifications()): Implemented.
+ * javax/management/NotificationBroadcaster.java:
+ (removeNotificationListener(NotificationListener)):
+ Renamed from removeListener.
+ * javax/management/NotificationEmitter.java:
+ (removeNotificationListener(NotificationListener,
+ NotificationFilter, Object)): Likewise.
+ * javax/management/NotificationFilter.java:
+ Implement Serializable.
+ * javax/management/NotificationListener.java:
+ Implement java.util.EventListener.
+ * javax/rmi/ssl/SslRMIClientSocketFactory.java:
+ Implement Serializable.
+
+2006-07-16 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/management/MemoryNotificationInfo.java:
+ New file.
+
+2006-07-16 Audrius Meskauskas <AudriusA@Bioinformatics.org>
+
+ PR 28392
+ * gnu/javax/swing/text/html/parser/htmlValidator.java
+ (tagIsValidForContext): If it is not possible to insert any tag, but
+ is possible to insert a P, insert a P.
+ * gnu/javax/swing/text/html/parser/HTML_401Swing.java
+ (newInstance): Removed print statement. (getBodyElements):
+ Removed ABBR, ACRONYM, BDO, Q, S, SUB, SUP and ADDRESS from the
+ valid body level tags (will be enclosed into P's).
+
+2006-07-17 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * tools/gnu/classpath/tools/keytool/Command.java (setKeystoreURLParam):
+ Condition the creation of .keystore (a default keystore) based on the
+ createIfNotFound argument as well.
+
+2006-07-16 Audrius Meskauskas <AudriusA@Bioinformatics.org>
+
+ PR 28392
+ * examples/gnu/classpath/examples/swing/HtmlDemo.java:
+ Removed heading p tag from the parsing example.
+ * gnu/javax/swing/text/html/parser/HTML_401F.java:
+ (createHtmlContentModel): Explained.
+ (defineElements): Call getBodyElements to get the body
+ elements. (getBodyElements): New method. (model):
+ Made protected from private.
+ * gnu/javax/swing/text/html/parser/htmlValidator.java
+ (openTag): Mind that current content model may be null.
+ (tagIsValidForContext): If the tag is PCDATA, and it is not
+ valid for context, but the paragraph (P) is valid for context,
+ suggest to insert the P tag here.
+ * javax/swing/text/html/HTMLDocument.java (HTMLReader.addContent,
+ HTMLReader.blockOpen, HTMLReader.blockClose): Do not handle
+ implied P tags here.
+ * javax/swing/text/html/HTMLEditorKit.java (getParser):
+ Get the custom parser, using HTML_401Swing.java DTD.
+ * javax/swing/text/html/parser/ParserDelegator.java:
+ Removed the obsolete note that HTMLEditorKit does not exist.
+ * gnu/javax/swing/text/html/parser/GnuParserDelegator.java,
+ gnu/javax/swing/text/html/parser/HTML_401Swing.java: New files.
+
+2006-07-16 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/ListenerNotFoundException.java:
+ New file.
+ * javax/management/MBeanFeatureInfo.java:
+ (hashCode()): Use summation instead of multiplication
+ for consistency with other classes.
+ * javax/management/MBeanNotificationInfo.java,
+ * javax/management/Notification.java,
+ * javax/management/NotificationBroadcaster.java,
+ * javax/management/NotificationEmitter.java,
+ * javax/management/NotificationFilter.java,
+ * javax/management/NotificationListener.java:
+ New files.
+ * javax/management/OperationsException.java:
+ (serialVersionUID): Added.
+
+2006-07-16 Thomas Minor <1nocentrabidlamb@sexMagnet.com>
+ Mark Wielaard <mark@klomp.org>
+
+ * java/io/PrintStream.java: Added four constructors, for File and
+ String describing a filename with or without explicit encoding.
+
+2006-07-16 Sven de Marothy <sven@physto.se>
+
+ * javax/rmi/ssl/SslRMIServerSocketFactory.java,
+ * javax/rmi/ssl/SslRMIClientSocketFactory.java:
+ New files.
+
+2006-07-16 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ PR Classpath/28391
+ * tools/gnu/classpath/tools/keytool/Command.java (setKeyStoreParams(5)):
+ New method.
+ (setKeyStoreParams(4)): Call the above method with false as its 1st arg.
+ (setProviderClassNameParam): Made private.
+ (setKeystoreTypeParam): Likewise.
+ (setKeyPasswordParam): Likewise
+ (setKeystorePasswordParam): Likewise.
+ (setKeystoreURLParam): Now accepts 2 more arguments; the first a boolean to
+ create or not the keystore if it's not there, and the second is the store's
+ password to process before loading the keystore. Amended the code
+ accordingly.
+ * tools/gnu/classpath/tools/keytool/GenKeyCmd.java (setup): Call super's
+ setKeyStoreParams(5) with true as its first argument.
+ * tools/gnu/classpath/tools/keytool/IdentityDBCmd.java (setup): Likewise.
+ * tools/gnu/classpath/tools/keytool/ImportCmd.java (setup): Likewise.
+
+2006-07-16 Sven de Marothy <sven@physto.se>
+
+ * java/util/UUID.java: New file.
+
+2006-07-16 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * gnu/javax/crypto/jce/cipher/KeyWrappingAlgorithmAdapter.java: New file.
+ * gnu/javax/crypto/jce/cipher/AESKeyWrapSpi.java: New file.
+ * gnu/javax/crypto/jce/cipher/AES128KeyWrapSpi.java: Likewise.
+ * gnu/javax/crypto/jce/cipher/AES192KeyWrapSpi.java: Likewise.
+ * gnu/javax/crypto/jce/cipher/AES256KeyWrapSpi.java: Likewise.
+ * gnu/javax/crypto/jce/cipher/TripleDESKeyWrapSpi.java: Likewise.
+ * gnu/javax/crypto/jce/GnuCrypto.java (.run): Added mappings for newly
+ added Key Wrapping Algorithm SPIs.
+
+2006-07-16 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * javax/crypto/Cipher.java (getOutputSize): Allow SPIs initialised for key
+ wrapping/unwrapping to invoke their engineGetOutputSize.
+
+2006-07-16 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * gnu/javax/crypto/kwa/TripleDESKeyWrap.java (rnd): New field.
+ (engineInit): If a SecureRandom was specified then use it.
+ (nextRandomBytes): New method.
+ (engineWrap): Use above method.
+ * gnu/javax/crypto/kwa/BaseKeyWrappingAlgorithm.java (prng): New field.
+ (getDefaultPRNG): New method.
+ * gnu/javax/crypto/kwa/AESKeyWrap.java (engineInit): Reset underlying AES.
+ * gnu/javax/crypto/kwa/IKeyWrappingAlgorithm.java (SOURCE_OF_RANDOMNESS):
+ New constant.
+
+2006-07-16 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * gnu/javax/crypto/jce/params/BlockCipherParameters.java
+ (engineGetParameterSpec): Should be able to return an IvParameterSpec.
+
+2006-07-16 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * gnu/javax/crypto/cipher/DES.java (adjustParity): Index limit now takes
+ offset into consideration.
+
+2006-07-16 Mario Torre <neugens@limasoftware.net>
+
+ * native/jni/gconf-peer/GConfNativePeer.c (init_gconf_client):
+ Fixed comment. This functions now requires to be called
+ with gdk lock held, the comment states that.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_init_1id_1cache):
+ Introduces gdk locks around critical regions of code.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1gconf_1client_1all_1keys):
+ Likewise.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1gconf_1client_1all_1nodes):
+ Likewise.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1suggest_1sync):
+ Likewise.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1unset):
+ Likewise.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1get_1string):
+ Likewise.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1set_1string):
+ Likewise.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1remove_1dir):
+ Likewise.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1add_1dir):
+ Likewise.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1dir_1exists):
+ Likewise.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_finalize_1class):
+ * native/jni/gconf-peer/Makefile.am: The GConf peer now depends on GTK.
+
+2006-07-15 Sven de Marothy <sven@physto.se>
+
+ * javax/swing/JFileChooser.java
+ Change default selection mode to FILES_ONLY.
+ * javax/swing/plaf/basic/BasicDirectoryModel.java
+ Document, fix selection mode filtering.
+ (renameFile): Implement
+ * javax/swing/plaf/basic/BasicFileChooserUI.java
+ (selectedDir): New field to handle selected directories,
+ disallow selecting of directories in FILES_ONLY mode.
+ * javax/swing/plaf/metal/MetalFileChooserUI.java:
+ (EditingActionListener.actionPerformed):
+ Stop editing on all actions (e.g. return-key press)
+
+2006-07-15 Mark Wielaard <mark@klomp.org>
+
+ * doc/vmintegration.texinfo (gnu.java.lang.management): Change xref
+ to code.
+ (JNI Implementation): Mark JVMTI Implementation as next.
+ (JVMTI Implementation): Mark JNI Implementation as prev.
+
+2006-07-15 Mark Wielaard <mark@klomp.org>
+
+ * include/Makefile.am: Remove
+ include/gnu_java_awt_peer_gtk_GdkTextLayout.h.
+ * include/gnu_java_awt_peer_gtk_GdkTextLayout.h: Removed.
+ * native/jni/gtk-peer/Makefile.am: Remove
+ gnu_java_awt_peer_gtk_GdkTextLayout.c
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c:
+ Removed.
+
+ * include/gnu_java_awt_peer_gtk_GtkWindowPeer.h: Regenerated.
+
+2006-07-15 Mark Wielaard <mark@klomp.org>
+
+ * autogen.sh: Recognize autoconf 2.60.
+
+2006-07-15 Keith Seitz <keiths@redhat.com>
+
+ * NEWS: Update for JVMTI and jvmti.h.
+ * doc/vmintegration.texinfo: Likewise.
+ * include/jvmti.h: New file.
+
+2006-07-15 Mark Wielaard <mark@klomp.org>
+
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c:
+ Removed C++ style comment.
+
+2006-07-15 Sven de Marothy <sven@physto.se>
+
+ * gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java,
+ * java/awt/MouseInfo.java,
+ * java/awt/PointerInfo.java,
+ * java/awt/peer/MouseInfoPeer.java:
+ New files.
+
+ * java/awt/Image.java
+ (accelerationPriority): New field.
+ (setAccelerationPriority, getAccelerationPriority): New methods..
+
+ * include/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h,
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c,
+ * gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java:
+ (getMouseCoordinates): New method.
+
+ * gnu/java/awt/peer/gtk/GtkFramePeer.java
+ (updateAlwaysOnTop): Remove stub overload.
+
+ * gnu/java/awt/ClasspathToolkit.java,
+ * gnu/java/awt/peer/gtk/GtkToolkit.java,
+ * include/gnu_java_awt_peer_gtk_GtkToolkit.h,
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c:
+ (getMouseInfoPeer): New method.
+ (getMouseNumberOfButtons): New method.
+
+ * gnu/java/awt/peer/gtk/GtkWindowPeer.java
+ * include/gnu_java_awt_peer_gtk_GtkWindowPeer.h
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
+ (gtkWindowSetAlwaysOnTop): New method.
+ (updateAlwaysOnTop): Implement.
+
+ * java/awt/Toolkit.java,
+ (getMouseInfoPeer): New method.
+
+ * java/awt/Window.java
+ (alwaysOnTop): New field.
+ (isAlwaysOnTop, setAlwaysOnTop): New methods.
+
+ * java/awt/peer/WindowPeer.java: Doc fix.
+
+2006-07-14 Sven de Marothy <sven@physto.se>
+
+ * java/awt/font/TextLayout.java:
+ (hitTestChar): Stub method.
+ * java/awt/font/TextMeasurer.java:
+ (getLayout): Throw exception on invalid argument.
+
+2006-07-14 Sven de Marothy <sven@physto.se>
+
+ * java/awt/image/DataBuffer.java
+ (DataBuffer): Call constructors in the correct order,
+
+2006-07-14 Mark Wielaard <mark@klomp.org>
+
+ Revert to previous implementation.
+ * java/awt/GridBagLayout.java (AdjustForGravity): Only adjust for
+ constraints insets.
+
+2006-07-14 Roman Kennke <kennke@aicas.com>
+
+ * gnu/java/awt/peer/x/XToolkit.java
+ (XToolkit): Install properties to SystemProperties
+ rather than System, to avoid SecurityManager.
+ (getImage(String)): Return error image when string is invalid.
+ (createImage(URL)): Moved image loading to helper method.
+ (createImage(ImageProducer)): Implemented.
+ (createImage(byte[],int,int)): Implemented.
+ (createImage(InputStream)): New helper method.
+
+2006-07-14 Tania Bento <tbento@redhat.com>
+
+ * java/awt/FlowLayout.java
+ (setHgap): No Excpetion should be thrown if hgap has
+ a negative value.
+ (setVgap): No Exception should be thrown if vgap has
+ a negative value.
+
+2006-07-14 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/MultiPixelPackedSampleModel.java:
+ Added API docs all over.
+
+2006-07-14 Matt Wringe <mwringe@redhat.com>
+
+ * gnu/javax/crypto/jce/cipher/CipherAdapter.java
+ (engineInit): Throw InvalidAlgorithmParameterException
+ for invalid IVParameterSpec IV length.
+
+2006-07-14 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/MultiPixelPackedSampleModel.java
+ (createDataBuffer): Include dataBitOffset in calculating the size for
+ the data buffer.
+
+2006-07-14 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/MultiPixelPackedSampleModel.java
+ (getSampleSize()): Return a copy of the array,
+ (getTransferType()): New method override.
+
+2006-07-14 Roman Kennke <kennke@aicas.com>
+
+ * java/awt/CardLayout.java
+ (show): Validate parent to make sure that the layout is
+ valid.
+
+2006-07-14 Roman Kennke <kennke@aicas.com>
+
+ * java/awt/Component.java
+ (enable): Added tree locking.
+ (disable): Added tree locking.
+ (show): Added tree locking.
+ (hide): Added tree locking.
+ (getLocationOnScreen): Added tree locking.
+ (reshape): Added tree locking.
+ (addHierarchyListener): Added tree locking.
+ (removeHierarchyListener): Added tree locking.
+ (addHierarchyBoundsListener): Added tree locking.
+ (removeHierarchyBoundsListener): Added tree locking.
+ (addNotify): Added tree locking.
+ (removeNotify): Added tree locking.
+ * java/awt/Container.java
+ (invalidateTree): Added tree locking.
+ (getAlignmentX): Added tree locking.
+ (getAlignmentY): Added tree locking.
+ (addNotify): Added tree locking.
+ (setComponentZOrder): Added tree locking.
+ (getComponentZOrder): Added tree locking.
+
+2006-07-14 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/MultiPixelPackedSampleModel.java
+ (createSubsetSampleModel): Restored argument check, but let null
+ through.
+
+2006-07-14 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/MultiPixelPackedSampleModel.java
+ (createSubsetSampleModel): Removed argument check.
+
+2006-07-14 Roman Kennke <kennke@aicas.com>
+
+ * java/awt/Component.java
+ (numHierarchyListeners): New field.
+ (numHierarchyBoundsListeners): New field.
+ (show): Fire hierarchy events here. Only fire component event
+ if there is actually a listener for it.
+ (hide): Fire hierarchy events here. Only fire component event
+ if there is actually a listener for it.
+ (reshape): Fire hierarchy events here. Only fire component event
+ if there is actually a listener for it.
+ (addHierarchyListeners): Update listener counters.
+ (removeHierarchyListeners): Update listener counters.
+ (addHierarchyBoundsListeners): Update listener counters.
+ (removeHierarchyBoundsListeners): Update listener counters.
+ (fireHierarchyEvent): New helper method for firing hierarchy
+ events.
+ * java/awt/Container.java
+ (addImpl): Update listener counters. Fire hierarchy event.
+ (remove): Update listener counters. Fire hierarchy event.
+ (fireHierarchyEvent): New helper method for firing hierarchy
+ events.
+ (updateHierarchyListenerCount): New helper method for
+ updating the listener counters.
+
+2006-07-14 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/MultiPixelPackedSampleModel.java
+ (equals): New method override,
+ (hashCode): Likewise.
+
+2006-07-14 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/MultiPixelPackedSampleModel.java
+ (MultiPixelPackedSampleModel(int, int, int, int, int, int)):
+ Corrected scanlineStride calculation.
+
+2006-07-14 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * gnu/java/security/Registry.java (KWA_PREFIX): New constant.
+ (AES_KWA): Likewise.
+ (AES128_KWA): Likewise.
+ (AES192_KWA): Likewise.
+ (AES256_KWA): Likewise.
+ (RIJNDAEL_KWA): Likewise.
+ (TRIPLEDES_KWA): Likewise.
+ (DESEDE_KWA): Likewise.
+ * gnu/javax/crypto/kwa/AESKeyWrap.java: New file
+ * gnu/javax/crypto/kwa/BaseKeyWrappingAlgorithm.java: Likewise.
+ * gnu/javax/crypto/kwa/IKeyWrappingAlgorithm.java: Likewise.
+ * gnu/javax/crypto/kwa/KeyUnwrappingException.java: Likewise.
+ * gnu/javax/crypto/kwa/KeyWrappingAlgorithmFactory.java: Likewise.
+ * gnu/javax/crypto/kwa/TripleDESKeyWrap.java: Likewise.
+
+2006-07-14 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * gnu/javax/crypto/pad/IPad.java: Updated class documentation.
+ (PADDING_BLOCK_SIZE): New constant.
+ (init(Map attributes)): New method.
+ * gnu/javax/crypto/pad/BasePad.java (init): New method.
+
+2006-07-14 Mario Torre <neugens@limasoftware.net>
+
+ * gnu/java/security/OID.java (OID): Private Constructor removed as
+ it is not needed anymore.
+ (clone): Fixed. Now uses super.clone instead of the private
+ constructor as per specification of clone method.
+ (serialVersionUID): added new field to allow serialization.
+
+2006-07-13 Sven de Marothy <sven@physto.se>
+
+ * gnu/javax/imageio/gif/GIFImageReader.java
+ (read): Remove old debugging trace.
+
+2006-07-13 Andreas Tobler <a.tobler@schweiz.ch>
+
+ PR awt/28369:
+ * gnu/java/awt/peer/gtk/CairoSurface.java (ColorModel): Swap red and
+ blue mask.
+
+2006-07-13 Roman Kennke <kennke@aicas.com>
+
+ * java/awt/Component.java
+ (DEFAULT_MAX_SIZE): New static constant.
+ (preferredSize): Return copy of the actual value computed
+ by new helper method.
+ (preferredSizeImpl): New helper method. Adds locking and
+ correct handling of cached value.
+ (minimumSize): Return copy of the actual value computed
+ by new helper method.
+ (minimumSizeImpl): New helper method. Adds locking and
+ correct handling of cached value.
+ (getMaximumSize): Return copy of the actual value computed
+ by new helper method.
+ (maximumSizeImpl): New helper method. Adds locking and
+ correct handling of cached value.
+ (invalidate): Correct handling of cached layout information.
+ Added locking.
+ * java/awt/Container.java
+ (preferredSize): Minimized locking. Corrected handling of cached
+ values. Return copy of real value.
+ (minimumSize): Minimized locking. Corrected handling of cached
+ values. Return copy of real value.
+ (getMaximumSize): Minimized locking. Corrected handling of cached
+ values. Return copy of real value.
+
+2006-07-13 Tania Bento <tbento@redhat.com>
+
+ * gnu/java/awt/peer/ClasspathFontPeer.java
+ (isLogicalFontName): Return true if name == default.
+ (logicalFontNameToFaceName): Check if name == default,
+ and if so, return "Dialog.plain".
+ (setStandardAttributes(String, Map)): If name == null,
+ it should be set to "Default", not "SansSerif".
+ * java/awt/Canvas.java
+ (generateName): Fixed documentation.
+ * java/awt/CheckboxMenuItem.java
+ Added static variable "next_chkmenuitem_number".
+ (generateName): Added and implemented method.
+ (getUniqueLong): Likewise.
+ * java/awt/Choice.java
+ Added static variable "next_choice_number".
+ (generateName): Added and implemented method.
+ (getUniqueLong): Likewise.
+ * java/awt/Cursor.java
+ (Cursor(int)): Set name depending on the type passed.
+ * java/awt/List.java
+ Added static variable "next_list_number".
+ (generateName): Added and implemented method.
+ (getUniqueLong): Likewise.
+ * java/awt/Menu.java
+ Added static variable "next_menu_number".
+ (generateName): Added and implemented method.
+ (getUniqueLong): Likewise.
+ * java/awt/MenuBar.java
+ Added static variable "next_menubar_number".
+ (generateName): Added and implemented method.
+ (getUniqueLong): Likewise.
+ * java/awt/MenuComponent.java
+ (getName): Before returning name, check if name == null
+ and name is not explicity set. If this is the case,
+ name will be generated.
+ (generateName): Added and implemented method.
+ * java/awt/MenuItem.java
+ Added static variable "next_menuitem_number".
+ (generateName): Added and implemented method.
+ (getUniqueLong): Likewise.
+ * java/awt/PopupMenu.java
+ Added static variable "next_popup_number".
+ (generateName): Added and implemented method.
+ (getUniqueLong): Likewise.
+ * java/awt/ScrollPane.java
+ Added static variable "next_scrollpane_number".
+ (generateName): Added and implemented method.
+ (getUniqueLong): Likewise.
+ * java/awt/TextField.java
+ Added static variable "next_textfield_number".
+ (generateName): Added and implemented method.
+ (getUniqueLong): Likewise.
+
+
+2006-07-13 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/SinglePixelPackedSampleModel.java
+ (SinglePixelPackageSampleModel(int, int, int, int, int[])): Convert
+ mask correctly as an unsigned integer,
+ (equals): New method override.
+
+2006-07-13 Audrius Meskauskas <AudriusA@Bioinformatics.org>
+
+ * javax/swing/text/html/HTMLDocument.java (insertAfterEnd,
+ insertAfterStart, insertBeforeEnd): Removed stub markings.
+
+2006-07-13 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/BandedSampleModel.java: API doc updates and source
+ code reformatting,
+ * java/awt/image/SinglePixelPackageSampleModel.java: Likewise.
+
+2006-07-13 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/BandedSampleModel.java: API doc updates.
+
+2006-07-13 Audrius Meskauskas <AudriusA@Bioinformatics.org>
+
+ * javax/swing/text/html/HTMLDocument.java (HTMLReader.parseStack):
+ Made package private. (HTMLReader.charAttr, HTMLReader.charAttrStack,
+ HTMLReader.insertTag, HTMLReader.insertTagEncountered,
+ HTMLReader.pushDepth, HTMLReader.popDepth): Documented.
+ (HRMLReader.blockClose): Mind that parser stack may be empty.
+ (HTMLReader.handeComment, HTMLReader.handleStartTag,
+ HTMLReader.handleEndTag, HTMLReader.handleSimpleTag): Rewritten.
+ (HTMLReader.shouldInsert): New method. (getElement(String)):
+ Pass HTML.Atrribute.ID. (insertAfterEnd, insertBeforeEnd,
+ insertAfterStart, insertBeforeStart, setInnerHTML, setOuterHTML):
+ Implemented. (getInsertingReader): New method.
+ * examples/gnu/classpath/examples/swing/HtmlDemo.java:
+ Added buttons to demonstrate the work of the insert actions.
+
+2006-07-13 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/SampleModel.java: API doc updates and additions,
+ * java/awt/image/SinglePixelPackedSampleModel.java: Likewise.
+
+2006-07-12 Sven de Marothy <sven@physto.se>
+
+ * javax/swing/JFileChooser.java:
+ (createDialog): Close operation should cause a cancel.
+
+2006-07-12 Francis Kung <fkung@redhat.com>
+
+ * gnu/java/awt/peer/gtk/CairoGraphics2D.java: Organized imports.
+ (cairoArc): New native method.
+ (cairoRestore): New native method.
+ (cairoSave): New native method.
+ (cairoScale): New native method.
+ (createPath): New method to centralize code from draw and fill.
+ (draw): Modified to use createPath method.
+ (fill): Modified to use createPath method.
+ * include/gnu_java_awt_peer_gtk_CairoGraphics2D.h: Added
+ function declarations.
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c
+ (Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoScale): New
+ method.
+ (Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSave): New
+ method.
+ (Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoArc): New
+ method.
+
+2006-07-12 Tom Tromey <tromey@redhat.com>
+
+ PR libgcj/27271:
+ * java/util/zip/ZipFile.java (getInputStream): Call addDummyByte
+ on PartialInputStream.
+ (PartialInputStream.dummyByteCount): New field.
+ (PartialInputStream.fillBuffer): Handle dummy byte.
+ (PartialInputStream.read): Likewise.
+ (PartialInputStream.addDummyByte): New method.
+
+2006-07-12 Mario Torre <neugens@limasoftware.net>
+
+ * native/jni/gconf-peer/GConfNativePeer.c
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1get_1string):
+ Fixed C++ style comment.
+
+2006-07-12 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/util/Arrays.java
+ (asList): Updated API docs.
+
+2006-07-11 Robert Schuster <robertschuster@fsfe.org>
+
+ Fixes PR28350.
+ * native/jni/gconf-peer/GConfNativePeer.c:
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1set_1string):
+ Changed if-expression.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1get_1string):
+ Added check for _value not being NULL.
+
+2006-07-11 Roman Kennke <kennke@aicas.com>
+
+ * native/jni/java-net/gnu_java_net_local_LocalSocketImpl.c
+ (read): Use fd when local sockets are disabled to make the
+ compiler quite.
+ (write): Likewise.
+
+2006-07-11 Roman Kennke <kennke@aicas.com>
+
+ * java/awt/image/MultiPixelPackedSampleModel.java
+ (MultiPixelPackedSampleModel): Substract -1 so that the integer
+ division gets rounded up.
+
+2006-07-11 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/management/ManageFactory.java:
+ (getMemoryManagerMXBeans()): Use addAll, not add.
+
+2006-07-11 Vivek Lakshmanan <vivekl@redhat.com>
+
+ PR 27649:
+ * gnu/classpath/ByteArray.java: Removed (moved).
+ * gnu/java/security/util/ByteArray.java: New File.
+ * gnu/javax/crypto/RSACipherImpl.java: Reference
+ gnu.java.security.util.ByteArray instead of gnu.classpath.ByteArray.
+
+2006-07-11 Roman Kennke <kennke@aicas.com>
+
+ * native/jni/java-net/gnu_java_net_local_LocalSocketImpl.c
+ (available): Pass fd as argument and avoid JNI class/field
+ lookup.
+ (read): Likewise.
+ (write): Likewise.
+ * include/gnu_java_net_local_LocalSocketImpl.h:
+ Regenerated.
+ * gnu/java/net/local/LocalSocketImpl.h
+ (available): Pass fd as argument and avoid JNI class/field
+ lookup.
+ (read): Likewise.
+ (write): Likewise.
+
+2006-07-11 Sven de Marothy <sven@physto.se>
+
+ * gnu/javax/sound/sampled/AU/AUReader.java:
+ Correct file extension from .as to .au.
+
+2006-07-11 Sven de Marothy <sven@physto.se>
+
+ * gnu/javax/sound/sampled/AU/AUReader.java:
+ New file.
+ * resource/META-INF/services/javax.sound.sampled.spi.AudioFileReader:
+ Added new provider.
+
+2006-07-11 David Gilbert <david.gilbert@object-refinery.com>
+
+ * javax/swing/JTable.java
+ (setRowSelectionAllowed): Fire required PropertyChangeEvent,
+ (setColumnSelectionAllowed): Likewise.
+
+2006-07-10 Vivek Lakshmanan <vivekl@redhat.com>
+
+ PR 27649:
+ * gnu/classpath/debug/Simple1LineFormatter.java: Use
+ AccessController.doPrivileged instead of SystemProperties.getProperty.
+ * gnu/classpath/debug/SystemLogger.java: Likewise.
+ * gnu/java/security/PolicyFile.java: Likewise and cut unnecessary
+ repeated getProperty calls for "file.seperator".
+ (refresh): Since already in privileged block, call System.getProperty
+ instead of SystemProperties.getProperty.
+ * gnu/java/security/key/dss/DSSKey.java
+ (toString): Use AccessController.doPrivileged instead of
+ SystemProperties.getProperty.
+ * gnu/java/security/key/dss/DSSPrivateKey.java
+ (toString): Likewise.
+ * gnu/java/security/key/dss/DSSPublicKey.java
+ (toString): Likewise.
+ * gnu/java/security/key/rsa/GnuRSAKey.java
+ (toString): Likewise.
+ * gnu/java/security/key/rsa/GnuRSAPrivateKey.java
+ (toString): Likewise.
+ * gnu/java/security/key/rsa/GnuRSAPublicKey.java
+ (toString): Likewise.
+ * gnu/javax/crypto/sasl/plain/PasswordFile.java: Likewise.
+ * gnu/javax/crypto/key/dh/GnuDHKey.java
+ (toString): Likewise.
+ * gnu/javax/crypto/key/dh/GnuDHPrivateKey.java
+ (toString): Likewise.
+ * gnu/javax/crypto/key/dh/GnuDHPublicKey.java
+ (toString): Likewise.
+
+2006-07-11 David Gilbert <david.gilbert@object-refinery.com>
+
+ * javax/swing/AbstractButton.java
+ (disabledIcon): Fixed name (was 'disabeldIcon'),
+ (getDisabledIcon): Updated for corrected field name,
+ (setDisabledIcon): Fire a PropertyChangeEvent.
+
+2006-07-11 David Gilbert <david.gilbert@object-refinery.com>
+
+ * javax/swing/DefaultBoundedRangeModel.java
+ (readObject): New private method,
+ (writeObject): Likewise.
+
+2006-07-11 David Gilbert <david.gilbert@object-refinery.com>
+
+ * javax/swing/ButtonGroup.java
+ (add): Ignore null argument,
+ (remove): Ignore null argument. If removing selected button, clear the
+ sel field,
+ (findButton): Changed case for method name, and documented,
+ (setSelected): Updated for modification to findButton() method name,
+ (isSelected): Updated API docs.
+
+2006-07-11 David Gilbert <david.gilbert@object-refinery.com>
+
+ * java/awt/image/BufferedImage.java
+ (BufferedImage(int, int, int)): Use correct color space for
+ TYPE_BYTE_GRAY and TYPE_USHORT_GRAY, and throw an
+ IllegalArgumentException for an unrecognised type.
+
+2006-07-10 Mario Torre <neugens@limasoftware.net>
+
+ * java/awt/BasicStroke.java: Removed unused import.
+ * gnu/java/awt/java2d/CubicSegment.java (clone): Fixed.
+ * gnu/java/awt/java2d/LineSegment.java (clone): Fixed.
+ * gnu/java/awt/java2d/QuadSegment.java (clone): Fixed.
+
+2006-07-10 Matt Wringe <mwringe@redhat.com>
+
+ PR classpath/28212:
+ * javax/crypto/spec/SecretKeySpec.java
+ (equals): Check object type.
+
+2006-07-10 Audrius Meskauskas <AudriusA@Bioinformatics.org>
+
+ * examples/gnu/classpath/examples/CORBA/SimpleCommunication/
+ communication/StructureToPassHelper.java,
+ examples/gnu/classpath/examples/CORBA/SimpleCommunication/
+ communication/StructureToReturnHelper.java,
+ examples/gnu/classpath/examples/CORBA/SimpleCommunication/
+ communication/TreeNodeHelper.java,
+ examples/gnu/classpath/examples/CORBA/SimpleCommunication/
+ communication/WeThrowThisExceptionHelper.java,
+ gnu/CORBA/ForwardRequestHelper.java,
+ org/omg/CORBA/CompletionStatusHelper.java,
+ org/omg/CORBA/CurrentHelper.java,
+ org/omg/CORBA/DefinitionKindHelper.java,
+ org/omg/CORBA/IDLTypeHelper.java,
+ org/omg/CORBA/NameValuePairHelper.java,
+ org/omg/CORBA/ObjectHelper.java,
+ org/omg/CORBA/ParameterModeHelper.java,
+ org/omg/CORBA/PolicyErrorCodeHelper.java,
+ org/omg/CORBA/PolicyErrorHelper.java,
+ org/omg/CORBA/PolicyHelper.java,
+ org/omg/CORBA/PolicyListHelper.java,
+ org/omg/CORBA/PolicyTypeHelper.java,
+ org/omg/CORBA/ServiceDetailHelper.java,
+ org/omg/CORBA/ServiceInformationHelper.java,
+ org/omg/CORBA/SetOverrideTypeHelper.java,
+ org/omg/CORBA/StringValueHelper.java,
+ org/omg/CORBA/UnionMemberHelper.java,
+ org/omg/CORBA/UnknownUserExceptionHelper.java,
+ org/omg/CORBA/VisibilityHelper.java,
+ org/omg/CORBA/WStringValueHelper.java,
+ org/omg/CORBA/WrongTransactionHelper.java,
+ org/omg/CosNaming/BindingHelper.java,
+ org/omg/CosNaming/BindingIteratorHelper.java,
+ org/omg/CosNaming/BindingListHelper.java,
+ org/omg/CosNaming/BindingTypeHelper.java,
+ org/omg/CosNaming/NameComponentHelper.java,
+ org/omg/CosNaming/NameHelper.java,
+ org/omg/CosNaming/NamingContextExtHelper.java,
+ org/omg/CosNaming/NamingContextExtPackage/AddressHelper.java,
+ org/omg/CosNaming/NamingContextExtPackage/InvalidAddressHelper.java,
+ org/omg/CosNaming/NamingContextExtPackage/StringNameHelper.java,
+ org/omg/CosNaming/NamingContextExtPackage/URLStringHelper.java,
+ org/omg/CosNaming/NamingContextHelper.java,
+ org/omg/CosNaming/NamingContextPackage/AlreadyBoundHelper.java,
+ org/omg/CosNaming/NamingContextPackage/CannotProceedHelper.java,
+ org/omg/CosNaming/NamingContextPackage/InvalidNameHelper.java,
+ org/omg/CosNaming/NamingContextPackage/NotEmptyHelper.java,
+ org/omg/CosNaming/NamingContextPackage/NotFoundHelper.java,
+ org/omg/CosNaming/NamingContextPackage/NotFoundReasonHelper.java,
+ org/omg/DynamicAny/AnySeqHelper.java,
+ org/omg/DynamicAny/DynAnyFactoryHelper.java,
+ org/omg/DynamicAny/DynAnyFactoryPackage/InconsistentTypeCodeHelper.java,
+ org/omg/DynamicAny/DynAnyHelper.java,
+ org/omg/DynamicAny/DynAnyPackage/InvalidValueHelper.java,
+ org/omg/DynamicAny/DynAnyPackage/TypeMismatchHelper.java,
+ org/omg/DynamicAny/DynAnySeqHelper.java,
+ org/omg/DynamicAny/DynArrayHelper.java,
+ org/omg/DynamicAny/DynEnumHelper.java,
+ org/omg/DynamicAny/DynFixedHelper.java,
+ org/omg/DynamicAny/DynSequenceHelper.java,
+ org/omg/DynamicAny/DynStructHelper.java,
+ org/omg/DynamicAny/DynUnionHelper.java,
+ org/omg/DynamicAny/DynValueHelper.java,
+ org/omg/DynamicAny/NameDynAnyPairHelper.java,
+ org/omg/DynamicAny/NameDynAnyPairSeqHelper.java,
+ org/omg/DynamicAny/NameValuePairHelper.java,
+ org/omg/DynamicAny/NameValuePairSeqHelper.java,
+ org/omg/IOP/CodecFactoryHelper.java,
+ org/omg/IOP/CodecFactoryPackage/UnknownEncodingHelper.java,
+ org/omg/IOP/CodecPackage/FormatMismatchHelper.java,
+ org/omg/IOP/CodecPackage/InvalidTypeForEncodingHelper.java,
+ org/omg/IOP/CodecPackage/TypeMismatchHelper.java,
+ org/omg/IOP/ComponentIdHelper.java,
+ org/omg/IOP/IORHelper.java,
+ org/omg/IOP/MultipleComponentProfileHelper.java,
+ org/omg/IOP/ProfileIdHelper.java,
+ org/omg/IOP/ServiceContextHelper.java,
+ org/omg/IOP/ServiceContextListHelper.java,
+ org/omg/IOP/ServiceIdHelper.java,
+ org/omg/IOP/TaggedComponentHelper.java,
+ org/omg/IOP/TaggedProfileHelper.java,
+ org/omg/PortableInterceptor/AdapterManagerIdHelper.java,
+ org/omg/PortableInterceptor/AdapterNameHelper.java,
+ org/omg/PortableInterceptor/AdapterStateHelper.java,
+ org/omg/PortableInterceptor/CurrentHelper.java,
+ org/omg/PortableInterceptor/ForwardRequestHelper.java,
+ org/omg/PortableInterceptor/IORInterceptor_3_0Helper.java,
+ org/omg/PortableInterceptor/InvalidSlotHelper.java,
+ org/omg/PortableInterceptor/ORBInitInfoPackage/DuplicateNameHelper.java,
+ org/omg/PortableInterceptor/ORBInitInfoPackage/InvalidNameHelper.java,
+ org/omg/PortableInterceptor/ObjectReferenceFactoryHelper.java,
+ org/omg/PortableInterceptor/ObjectReferenceTemplateHelper.java,
+ org/omg/PortableInterceptor/ObjectReferenceTemplateSeqHelper.java,
+ org/omg/PortableServer/CurrentHelper.java,
+ org/omg/PortableServer/CurrentPackage/NoContextHelper.java,
+ org/omg/PortableServer/ForwardRequestHelper.java,
+ org/omg/PortableServer/POAHelper.java,
+ org/omg/PortableServer/POAManagerPackage/AdapterInactiveHelper.java,
+ org/omg/PortableServer/POAPackage/AdapterAlreadyExistsHelper.java,
+ org/omg/PortableServer/POAPackage/AdapterNonExistentHelper.java,
+ org/omg/PortableServer/POAPackage/InvalidPolicyHelper.java,
+ org/omg/PortableServer/POAPackage/NoServantHelper.java,
+ org/omg/PortableServer/POAPackage/ObjectAlreadyActiveHelper.java,
+ org/omg/PortableServer/POAPackage/ObjectNotActiveHelper.java,
+ org/omg/PortableServer/POAPackage/ServantAlreadyActiveHelper.java,
+ org/omg/PortableServer/POAPackage/ServantNotActiveHelper.java,
+ org/omg/PortableServer/POAPackage/WrongAdapterHelper.java,
+ org/omg/PortableServer/POAPackage/WrongPolicyHelper.java,
+ org/omg/PortableServer/ServantActivatorHelper.java,
+ org/omg/PortableServer/ServantLocatorHelper.java: Remove the
+ typecode caching and always use OrbRestricted.Singleton.
+
+2006-07-09 Mark Wielaard <mark@klomp.org>
+
+ * gnu/java/awt/peer/gtk/ComponentGraphics.java (hasXRenderExtension):
+ New static final boolean field.
+ (getComponentGraphics): Use hasXRenderExtension.
+ (setClip): Override method for locking.
+
+2006-07-09 David Gilbert <david.gilbert@object-refinery.com>
+
+ * javax/swing/AbstractButton.java
+ (setHorizontalTextPosition): Added check for illegal argument,
+ (setVerticalTextPosition): Likewise.
+
+2006-07-09 David Gilbert <david.gilbert@object-refinery.com>
+
+ * javax/swing/Timer.java
+ (setDelay): Throw IllegalArgumentException for negative delay,
+ (setInitialDelay): Likewise,
+ * javax/swing/ToolTipManager.java
+ (setInitialDelay): Document IllegalArgumentException,
+ (setDismissDelay): Likewise,
+ (setReshowDelay): Likewise.
+
+2006-07-09 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/management/MemoryUsage.java:
+ (from(javax.management.openmbean.CompositeData)):
+ Implemented.
+ * java/lang/management/ThreadInfo.java:
+ Changed to use open types throughout for the state.
+ (ThreadInfo(long,String,String,long,long,String,
+ long,String,long,long,boolean,StackTraceElement[])):
+ New constructor.
+ (checkAttribute(javax.management.openmbean.CompositeType,
+ String, javax.management.openmbean.OpenType)): New method.
+ (from(javax.management.openmbean.CompositeData)):
+ Implemented.
+ (getLockName()): Fixed to use new variable.
+ (getLockOwnerId()): Likewise.
+ (getLockOwnerName()): Likewise.
+ (getThreadId()): Likewise.
+ (getThreadName()): Likewise.
+ (getThreadState()): Likewise.
+ (toString()): Refactored to use new variables.
+ * javax/management/openmbean/ArrayType.java:
+ New file.
+ * javax/management/openmbean/CompositeType.java:
+ Variables should be transient, not volatile.
+ * javax/management/openmbean/OpenDataException.java:
+ (serialVersionUID): Added.
+ * javax/management/openmbean/SimpleType.java:
+ New file.
+ * javax/management/openmbean/TabularType.java
+ Variables should be transient, not volatile.
+
+2006-07-09 Tom Tromey <tromey@redhat.com>
+
+ * tools/.cvsignore: Updated for new tools.
+
+2006-07-09 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/openmbean/CompositeData.java,
+ * javax/management/openmbean/CompositeType.java,
+ * javax/management/openmbean/OpenDataException.java,
+ * javax/management/openmbean/OpenType.java,
+ * javax/management/openmbean/TabularData.java,
+ * javax/management/openmbean/TabularType.java,
+ * javax/management/openmbean/package.html:
+ New files.
+
+2006-07-09 Mark Wielaard <mark@klomp.org>
+
+ * gnu/javax/print/ipp/IppRequest.java: Remove double assignment.
+ * gnu/java/rmi/server/UnicastServerRef.java: Likewise.
+ * gnu/java/rmi/server/ActivatableServerRef.java: Likewise.
+
+2006-07-08 Anthony Green <green@redhat.com>
+
+ * gnu/javax/sound/sampled/WAV/WAVReader.java,
+ resource/META-INF/services/javax.sound.sampled.spi.AudioFileReader:
+ New files.
+
+2006-07-09 Mario Torre <neugens@limasoftware.net>
+
+ * native/jni/gconf-peer/GConfNativePeer.c:
+ Fixed indentation to be more compliant to the GNU coding
+ guidelines.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1unset):
+ Added explicit test for errors in the GConf backend.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1get_1string):
+ Added explicit test for errors in the GConf backend.
+ Fixed Segmentation Fault when non valid key names are given as input.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1set_1string):
+ likewise.
+ (Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1dir_1exists):
+ Added explicit test for errors in the GConf backend.
+ * gnu/java/util/prefs/gconf/GConfNativePeer.java:
+ Added javadoc comments for all native methods.
+ (nodeExist): removed test to check for valid absolute path name
+ for nodes.
+ (startWatchingNode): likewise.
+ (stopWatchingNode): likewise.
+ (setString): likewise, plus fixed javadoc comments.
+ (unset): likekwise.
+ (getKey): likewise.
+ (getKeys): likewise, also fixed javadoc comments.
+ (getChildrenNodes): likewise.
+ * gnu/java/util/prefs/GConfBasedPreferences.java:
+ changed DEFAULT_USER_ROOT to /apps/classpath.
+ (constructor): Test to check for a valid absolute path for nodes
+ is now in the contructor for that node, instead of being on
+ each method of the backend.
+ (getGConfKey): removed empty new line.
+
2006-07-08 Mark Wielaard <mark@klomp.org>
* .classpath: Add gnu/java/awt/peer/x/ to excludes.
diff --git a/ChangeLog.native b/ChangeLog.native
index 64a5fd27a..818ca64fd 100644
--- a/ChangeLog.native
+++ b/ChangeLog.native
@@ -1,6 +1,10 @@
+2006-08-14 Guilhem Lavaux <guilhem@kaffe.org>
+
+ * Merged HEAD as of 2006-08-14 0:00.
+
2006-07-09 Guilhem Lavaux <guilhem@kaffe.org>
- * Merged HEAD as of 2006-06-09 0:00.
+ * Merged HEAD as of 2006-07-09 0:00.
2006-07-09 Guilhem Lavaux <guilhem@kaffe.org>
diff --git a/INSTALL b/INSTALL
index 97983fdce..d2bb26621 100644
--- a/INSTALL
+++ b/INSTALL
@@ -59,6 +59,11 @@ Suggested Software
- Qt 4.0.1
+ For building the X AWT peers see information below
+ (Building and running with the X AWT peers). You will need
+ the Escher 0.2.3 library:
+ http://escher.sourceforge.net
+
Please note that at the moment most operating systems do not
ship Qt4 by default. We recommend using GNU Classpath' Qt4
support only for its developers and bug reporters. See
@@ -75,6 +80,13 @@ Suggested Software
http://www.xmlsoft.org/XSLT/
Minimum version of libxslt required: 1.1.11
+ For building the javah tool, you will need the ASM library.
+ Current version 2.2.1 is needed (other 2.2.x versions should
+ be ok; 3.x is not ok). You can get ASM from
+ http://asm.objectweb.org/
+ You will need to pass the --with-asm option to configure
+ and point it at your ASM jar file.
+
For building the documentation you will need
- texinfo 4.2 or higher.
@@ -119,10 +131,18 @@ gives a complete list.
default=no
--enable-xmlj compile native libxml/xslt library default=no
--enable-load-library enable to use JNI native methods default=yes
+ --enable-local-sockets enable build of local Unix sockets
+ --with-asm=/path/to/asm.jar
+ the ASM jar to use for javah
--with-jikes to compile the class library using jikes
the default is to use gcj
--with-glibj define what to install (zip|flat|both|none)
default=zip
+ --with-escher=/path/to/escher
+ enable build of the X/Escher peers, with
+ the escher library at /path/to/escher, either
+ in the form of a JAR file, or a directory
+ containing the .class files of Escher.
--enable-Werror whether to compile C code with -Werror which turns
any compiler warning into a compilation failure
default=no
@@ -164,6 +184,25 @@ More information about the VMs that use GNU Classpath can be found in the
README file.
------------------------------------------------------------------
+Building and running with the X AWT peers
+------------------------------------------------------------------
+
+In order build the X peers you need the Escher library version 0.2.3
+from http://escher.sourceforge.net . Unpack (and optionally build) the
+Escher library following the instructions in the downloaded
+package. Enable the build of the X peers by passing
+--with-escher=/path/to/escher to ./configure where /path/to/escher
+either points to a directory structure or JAR file containing the
+Escher classes. For Unix systems it is preferable to also build local
+socket support by passing --enable-local-sockets, which accelerates
+the network communication to the X server significantly.
+
+In this release you have to enable the X peers at runtime by
+setting the system property awt.toolkit=gnu.java.awt.peer.x.XToolkit
+by passing -Dawt.toolkit=gnu.java.awt.peer.x.XToolkit to the java
+command when running an application.
+
+------------------------------------------------------------------
Misc. Notes
------------------------------------------------------------------
Compilation is accomplished using a compiler's @file syntax. For our
diff --git a/NEWS b/NEWS
index e0f306af3..3de8439f8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,12 @@
-New in release 0.92 (UNRELEASED)
+New in release 0.93 (UNRELEASED)
+
+* The 'javah' tool has been added. It requires the ASM library
+ (see asm.objectweb.org); it can be enabled with the --with-asm
+ option to configure
+* Added the rmi and corbaname URL context factories for JNDI.
+* Fixes in the JNDI InitialContext now allows to plug-in user implementation.
+
+New in release 0.92 (Aug 9, 2006)
* libjawtgnu.so has been renamed libjawt.so for binary compatibility.
libjawt.so should be installed in a VM-specific directory rather
@@ -13,8 +21,9 @@ New in release 0.92 (UNRELEASED)
build the GTK peers.
* A Mozilla plugin, 'gcjwebplugin', is now included. It introduces a
dependency on the Mozilla plugin support headers and libraries.
-* A tools.texinfo document has been created and now includes documentation
- about:
+* New java implementations of png and gif imageio readers and writers.
+* A tools.texinfo document has been created and now includes
+ documentation about:
* appletviewer
* gcjwebplugin
* jarsigner
@@ -30,6 +39,19 @@ New in release 0.92 (UNRELEASED)
binaries to be built for VMs that support the JNI Invocation API.
* javax.sound.midi providers have been added to read and
write standard MIDI files.
+* A javax.sound.sampled .au and .wav file readers have been added.
+* New Java Virtual Machine Tool Interface header, jvmti.h.
+* AWT peers for X Windows based on Escher (a pure java X protocol
+ implementation) have been added. So far it supports AWT 1.1 style
+ Graphics, image loading via ImageIO (PNG, GIF and BMP images in this
+ release), top level components as well as mouse and keyboard input.
+ It is capable of running many Swing applications. Graphics2D and
+ AWT widgets are not yet supported with this peer set.
+* GConf based util.peers backend (see the --enable-gconf-peer and
+ --enable-default-preferences-peer configure options).
+* Support for batch importing trusted certificates for use with ssl
+ connections (see script/import-cacerts.sh).
+* NIO scatter-gather channel support.
Runtime interface changes:
diff --git a/README b/README
index 132fbe531..d2e38a5db 100644
--- a/README
+++ b/README
@@ -1,21 +1,21 @@
-GNU Classpath README - Last updated: May 15, 2006
+GNU Classpath README - Last updated: August 6, 2006 (for release 0.92)
GNU Classpath, Essential Libraries for Java is a project to create a
free software implementation of the core class libraries for the java
programming language.
-Additionally GNU Classpath includes a sub-project called GNU Classpath
-Tools whose goal is to provide a number of free replacements for
-standard Java development tools like javadoc, javap, javah, and
-others. And a sub-project called GNU Inetlib, an extension library to
-provide extra network protocol support (ftp, finger, gopher) for GNU
-Classpath, but it can also standalone to ease adding http, imap, pop3
-and smtp client support to applictions. These subprojects are normally
-released independent from the core libraries.
+Additionally, GNU Classpath includes a sub-project called GNU Classpath
+Tools whose goal is to provide a number of free replacements for standard
+Java development tools like javadoc, javap, and others. A sub-project
+called GNU Inetlib, can be used as an extension library to provide extra
+network protocol support (ftp, finger, gopher) for GNU Classpath. It can
+also be used as a standalone to ease adding http, imap, pop3 and smtp
+client support to applictions. These subprojects are normally released
+independently from the core libraries.
This is a development snapshot release only and is not for general
-purpose use. GNU Classpath needs to be combine with a proper
-development environments to be useable for end users. Eventually,
+purpose use. GNU Classpath needs to be combined with a proper
+development environment to be useable for end users. Eventually,
these essential libraries for java will work with as many free
compilers and runtimes as possible.
@@ -31,24 +31,22 @@ with this GNU Classpath releases include
* CACAO (http://www.cacaojvm.org/)
* JamVM (http://jamvm.sourceforge.net/)
- * Jikes RVM (http://www.ibm.com/developerworks/oss/jikesrvm/)
- * Kissme (http://kissme.sourceforge.net/)
+ * Jikes RVM (http://jikesrvm.sourceforge.net/)
In general the latest releases of the above VMs will work out of the box
with the latest GNU Classpath release (and in most cases directly with the
development sources from CVS).
Besides combining GNU Classpath with the runtimes and compilers above
-you might want to add support for encryption libraries as provided by
-GNU Crypto (http://www.gnu.org/software/gnu-crypto/).
-And for additional extension libraries (mail, xml, activation, infobus,
-servlet) check out GNU ClasspathX (http://www.gnu.org/software/classpathx).
+you might want to add support for additional extension libraries (mail,
+activation, infobus, servlet) check out the GNU ClasspathX project
+(http://www.gnu.org/software/classpathx/).
Some tools come with their own customized version of GNU Classpath.
-Please check if there is a customised version available for the tool you
-use before trying the bare bones GNU Classpath release. We are working with
+Please check if there is a customized version available for the tool you
+use before trying the bare bones GNU Classpath release. We are working with
the tool creators to keep the differences between the core classes as small
-as possible. Please tell us if you make GNU Classpath work with a new tool.
+as possible. Please tell us if you make GNU Classpath work with a new tool.
Active projects which use modified versions of the Classpath libraries
some of which synchronizes with the Classpath CVS head every couple of weeks:
@@ -57,9 +55,9 @@ some of which synchronizes with the Classpath CVS head every couple of weeks:
* JC (http://jcvm.sourceforge.net/)
* JNode (http://jnode.sourceforge.net/)
* MysaifuVM (http://www2s.biglobe.ne.jp/~dat/java/project/jvm/)
- * SableVM (http://www.sablevm.org)
+ * SableVM (http://www.sablevm.org/)
-See for a more complete list of GNU Classpath based projects the
+For a more complete list of GNU Classpath based projects, see the
GNU Classpath website: http://www.gnu.org/software/classpath/stories.html
See the file INSTALL for details on installing GNU Classpath.
@@ -69,23 +67,25 @@ See the file HACKING for working on (non-released) CVS development versions.
Homepage: http://www.gnu.org/software/classpath/
+Bugs should be reported via bugzilla, available from the GNU Classpath
+website: http://www.gnu.org/software/classpath/bugs.html
+
General Mailing List: classpath@gnu.org
- --> Bugs and patches can be reported via Savannah if you have a browser
- or via this address otherwise.
--> To subscribe send email to classpath-request@gnu.org with a
subject and body of "subscribe". To unsubscribe do the same,
only with a body and subject of "unsubscribe". This is a
smartlist managed mailing list.
-CVS Commit, Bugs and Patches List: commit-classpath@gnu.org
- --> To subscribe send email to commit-classpath-request@gnu.org with a
+Patches Mailing List: classpath-patches@gnu.org
+ --> Proposed patches should be sent to the GNU Classpath patches list
+ --> To subscribe send email to classpath-patches-request@gnu.org with a
subject and body of "subscribe". To unsubscribe do the same,
only with a body and subject of "unsubscribe". This is a
smartlist managed mailing list.
Anonymous CVS:
- --> export CVS_RSH="ssh"
- --> cvs -z3 -d:ext:anoncvs@savannah.gnu.org:/cvsroot/classpath co classpath
+ --> "cvs -z3 -d:pserver:anonymous@cvs.savannah.gnu.org:/sources/classpath
+ co classpath"
--> More detailed instructions available on the Savannah project website.
http://savannah.gnu.org/projects/classpath/
diff --git a/autogen.sh b/autogen.sh
index babfa4e5d..9919d15b4 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -41,11 +41,14 @@ if autoconf --version < /dev/null > /dev/null 2>&1 ; then
2.59*)
have_autoconf=true
;;
+ 2.60*)
+ have_autoconf=true
+ ;;
esac
fi
if $have_autoconf ; then : ; else
echo
- echo "You must have autoconf 2.59 installed to compile $PROJECT."
+ echo "You must have autoconf 2.59 or 2.60 installed for $PROJECT."
echo "Install the appropriate package for your distribution,"
echo "or get the source tarball at http://ftp.gnu.org/gnu/autoconf/"
DIE=1
diff --git a/configure.ac b/configure.ac
index 70b3f4916..51f8b015e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@ dnl -----------------------------------------------------------
dnl define([AC_CACHE_LOAD], )dnl
dnl define([AC_CACHE_SAVE], )dnl
-AC_INIT([GNU Classpath],[0.92-pre],[classpath@gnu.org],[classpath])
+AC_INIT([GNU Classpath],[0.93-pre],[classpath@gnu.org],[classpath])
AC_CONFIG_SRCDIR(java/lang/System.java)
AC_CANONICAL_TARGET
@@ -85,13 +85,17 @@ AM_CONDITIONAL(CREATE_CORE_JNI_LIBRARIES, test "x${COMPILE_CORE_JNI}" = xyes)
dnl -----------------------------------------------------------
dnl Default Preference Backend
dnl -----------------------------------------------------------
-AC_ARG_ENABLE(default-preferences-peer,
- AS_HELP_STRING([--enable-default-preferences-peer],
- [fully qualified class name of default Preferences API Backend]))
-DEFAULT_PREFS_PEER=$enable_default_preferences_peer
-if test "$DEFAULT_PREFS_PEER" = ""; then
- DEFAULT_PREFS_PEER=gnu.java.util.prefs.FileBasedFactory
-fi
+AC_ARG_ENABLE([default-preferences-peer],
+ [AS_HELP_STRING([--enable-default-preferences-peer@<:@=peer type or class name@:>@],
+ [specify one of: "gconf" [default] for a GConf based backend, "file" for a file based one, "memory" for a transient one, or a fully qualified class name implementing java.util.prefs.PreferencesFactory])],
+ [case "${enableval}" in
+ file) DEFAULT_PREFS_PEER=gnu.java.util.prefs.FileBasedFactory ;;
+ gconf|yes|true) DEFAULT_PREFS_PEER=gnu.java.util.prefs.GConfBasedFactory ;;
+ memory) DEFAULT_PREFS_PEER=gnu.java.util.prefs.MemoryBasedFactory ;;
+ no|false) AC_MSG_ERROR(bad value '${enableval}' for --enable-default-preferences-peer) ;;
+ *) DEFAULT_PREFS_PEER=${enableval} ;;
+ esac],
+ [DEFAULT_PREFS_PEER=gnu.java.util.prefs.GConfBasedFactory])
dnl AC_SUBST(DEFAULT_PREFS_PEER)
dnl -----------------------------------------------------------
@@ -120,9 +124,9 @@ AC_ARG_ENABLE([Werror],
[case "${enableval}" in
yes) ENABLE_WERROR=yes ;;
no) ENABLE_WERROR=no ;;
- *) ENABLE_WERROR=no ;;
+ *) ENABLE_WERROR=default ;;
esac],
- [ENABLE_WERROR=no])
+ [ENABLE_WERROR=default])
dnl -----------------------------------------------------------
dnl Default AWT toolkit
@@ -305,6 +309,17 @@ dnl AC_PROG_AWK
AC_PROG_CC
AC_PROG_CPP
+# Handle -Werror default case.
+if test "$ENABLE_WERROR" = default; then
+ case "$host_os" in
+ *linux*)
+ if test "$GCC" = yes; then
+ ENABLE_WERROR=yes
+ fi
+ ;;
+ esac
+fi
+
if test "x${COMPILE_COLLECTIONS}" = xyes; then
AC_PATH_PROG(PERL, [perl])
AC_SUBST(PERL)
@@ -469,6 +484,10 @@ if test "x${COMPILE_JNI}" = xyes; then
PKG_CHECK_MODULES(GCONF, gconf-2.0 >= 2.11.2)
AC_SUBST(GCONF_CFLAGS)
AC_SUBST(GCONF_LIBS)
+ dnl we also need gdk for locking
+ PKG_CHECK_MODULES(GDK, gdk-2.0 >= 2.8)
+ AC_SUBST(GDK_CFLAGS)
+ AC_SUBST(GDK_LIBS)
dnl check if the config value was given form the command line,
dnl if not, overwrite the default if we have the gconf backend
dnl compiled in
@@ -492,6 +511,7 @@ if test "x${COMPILE_JNI}" = xyes; then
QT_CFLAGS="$QT_CFLAGS -I$EXTRA_QT_INCLUDE_DIR",
AC_MSG_WARN([QWidget not found])))
AC_CHECK_PROG(MOC, [moc], [moc])
+ AC_CHECK_PROG(MOC, [moc-qt4], [moc-qt4])
fi
if test "x$HAVE_QT4" = "xno"; then
AC_MSG_NOTICE([Looking for QT_CFLAGS and QT_LIBS without pkg-config])
@@ -536,6 +556,9 @@ if test "x${COMPILE_JNI}" = xyes; then
if test "x${MOZILLA_FOUND}" = xno; then
PKG_CHECK_MODULES(MOZILLA, xulrunner-plugin, [MOZILLA_FOUND=yes], [MOZILLA_FOUND=no])
fi
+ if test "x${MOZILLA_FOUND}" = xno; then
+ PKG_CHECK_MODULES(MOZILLA, mozilla-firefox-plugin, [MOZILLA_FOUND=yes], [MOZILLA_FOUND=no])
+ fi
PKG_CHECK_MODULES(GLIB, glib-2.0)
AC_SUBST(MOZILLA_CFLAGS)
@@ -731,18 +754,43 @@ case "$with_escher" in
use_escher=false
;;
"yes")
- AC_MSG_ERROR([Please suply an absolute path to Escher library])
+ AC_MSG_ERROR([Please supply an absolute path to Escher library])
;;
*)
use_escher=true
PATH_TO_ESCHER=$with_escher
;;
-esac;
+esac
AM_CONDITIONAL(USE_ESCHER, test x$use_escher = xtrue)
AC_SUBST(PATH_TO_ESCHER)
dnl -----------------------------------------------------------
+dnl Build javah using ASM library
+dnl -----------------------------------------------------------
+AC_ARG_WITH([asm],
+ AS_HELP_STRING([--with-asm=ABS.PATH],
+ [specify path to ASM jar for javah]))
+case "$with_asm" in
+"")
+ use_asm=false
+ ;;
+"no")
+ use_asm=false
+ ;;
+"yes")
+ AC_MSG_ERROR([Please supply an absolute path to ASM jar])
+ ;;
+*)
+ use_asm=true
+ PATH_TO_ASM=$with_asm
+ ;;
+esac
+
+AM_CONDITIONAL(USE_ASM, test x$use_asm = xtrue)
+AC_SUBST(PATH_TO_ASM)
+
+dnl -----------------------------------------------------------
dnl Check if local socket support should be included.
dnl -----------------------------------------------------------
AC_ARG_ENABLE([local-sockets],
@@ -810,7 +858,8 @@ lib/gen-classlist.sh
lib/copy-vmresources.sh
tools/Makefile
examples/Makefile
-examples/Makefile.jawt])
+examples/Makefile.jawt
+examples/Makefile.java2d])
if test "x${COMPILE_WRAPPERS}" = xno
then
@@ -826,6 +875,11 @@ AC_CONFIG_COMMANDS([gkeytool],[chmod 755 tools/gkeytool])
AC_CONFIG_COMMANDS([gjar],[chmod 755 tools/gjar])
AC_CONFIG_COMMANDS([gnative2ascii],[chmod 755 tools/gnative2ascii])
AC_CONFIG_COMMANDS([gserialver],[chmod 755 tools/gserialver])
+
+ if test "$use_asm" = true; then
+ AC_CONFIG_FILES([tools/gjavah])
+ AC_CONFIG_COMMANDS([gjavah], [chmod 755 tools/gjavah])
+ fi
fi
AC_CONFIG_COMMANDS([gen-classlist],[chmod 755 lib/gen-classlist.sh])
@@ -837,4 +891,3 @@ cat ${srcdir}/lib/standard.omit.in > lib/standard.omit
if test x$use_escher != xtrue; then
echo gnu/java/awt/peer/x/.*java$ >> lib/standard.omit
fi
-
diff --git a/doc/vmintegration.texinfo b/doc/vmintegration.texinfo
index 02c81b5cf..e7f85d088 100644
--- a/doc/vmintegration.texinfo
+++ b/doc/vmintegration.texinfo
@@ -12,7 +12,7 @@ This file contains important information you will need to know if you
are going to write an interface between GNU Classpath and a Virtual
Machine.
-Copyright (C) 1998-2002, 2004, 2005 Free Software Foundation, Inc.
+Copyright (C) 1998-2002, 2004, 2005, 2006 Free Software Foundation, Inc.
@ifnotplaintext
@dircategory GNU Libraries
@@ -66,6 +66,7 @@ This document is incomplete, as we are still in alpha with the interface.
* Classpath Hooks:: Hooks from Classpath to the VM
* VM Hooks:: Hooks from the underlying VM to Classpath
* JNI Implementation:: Hooking the VM to jni.h
+* JVMTI Implementation:: Hooking the VM to jvmti.h
* Miscellaneous VM Requirements::
@end menu
@@ -1550,6 +1551,9 @@ of names of memory managers which manage the specified pool.
@item @code{(getPeakUsage(String))} -- Returns a
@code{java.lang.management.MemoryUsage} object for the peak
usage level of the specified pool.
+@item @code{(getType(String))} -- Returns a string containing
+either @code{"HEAP"} or @code{"NON_HEAP"} which indicates the type of
+memory used by the specified pool.
@item @code{(getUsage(String))} -- Returns a
@code{java.lang.management.MemoryUsage} object for the current
usage level of the specified pool.
@@ -1605,7 +1609,7 @@ number of milliseconds for which the garbage collector has run.
@end itemize
Note that each garbage collector is also a memory manager, and so an
-implementation of the @xref{gnu.java.lang.management.VMMemoryManagerMXBeanImpl}
+implementation of the @code{gnu.java.lang.management.VMMemoryManagerMXBeanImpl}
methods for its name should also be provided.
@node java.lang.management, Classpath Callbacks, gnu.java.lang.management, Classpath Hooks
@@ -1648,6 +1652,26 @@ the group.
@item @code{java.lang.ThreadGroup.removeThread(Thread)}
Call this method from @code{Thread} when a @code{Thread} is stopped or destroyed.
+
+@item @code{gnu.java.lang.management.MemoryMXBeanImpl.fireThresholdExceededNotification(String, long, long, long, long)}
+If the monitoring of memory usage thresholds is supported, this method
+should be called when the normal usage of a memory pool crosses the
+threshold, in order to emit a notification. Another notification
+should not be emitted until there is an intermittent period where the
+usage is again below the threshold. The parameters are the memory
+pool name, the usage levels (init, used, committed and max) and the
+number of times the threshold has been crossed.
+
+@item @code{gnu.java.lang.management.MemoryMXBeanImpl.fireCollectionThresholdExceededNotification(String, long, long, long, long)}
+If the monitoring of memory usage thresholds is supported, this method
+should be called when the usage of a memory pool after a garbage
+collection cycle crosses the threshold, in order to emit a
+notification. Another notification should not be emitted until there
+is an intermittent period where the usage is again below the
+threshold. The parameters are the memory pool name, the usage levels
+(init, used, committed and max) and the number of times the threshold
+has been crossed.
+
@end itemize
@node VM Hooks, JNI Implementation, Classpath Hooks, Top
@@ -1748,7 +1772,7 @@ reinitialize it yourself, there should be no harm.
@end itemize
-@node JNI Implementation, Miscellaneous VM Requirements, VM Hooks, Top
+@node JNI Implementation, JVMTI Implementation, VM Hooks, Top
@comment node-name, next, previous, up
@chapter JNI Implementation
@@ -1791,8 +1815,33 @@ be a sequence of field declarations.
@end itemize
+@node JVMTI Implementation, Miscellaneous VM Requirements, JNI Implementation, Top
+@comment node-name, next, previous, up
+@chapter JVMTI Implementation
+
+Classpath comes with its own implementation of @file{jvmti.h}. This
+file can be customized by the VM in a few ways by defining macros that
+affect the interpretation of the file. These macros are all intended
+for use for use by a VM which uses GNU Classpath and which wants to
+use a single copy of @file{jvmti.h} for both internal and external use.
+
+@itemize @bullet
+@item _CLASSPATH_VM_JVMTI_TYPES_DEFINED
+Some VMs like to define JVMTI ``object'' types in a special way. If
+this macro is defined, the Classpath @file{jvmti.h} will avoid defining
+these types. By default these types are defined in @file{jvmti.h}.
+The full list of types and macros treated this way is: @samp{jthread},
+@samp{jthreadGroup}, @samp{jlocation}, and @samp{jrawMonitorID}. By
+default @samp{jrawMonitorID} is defined as an opaque pointer which
+must be defined by the VM.
+
+@item _CLASSPATH_JVMTIENV_CONTENTS
+A VM can add fields to the @samp{jvmtiEnv} structure by defining this
+to be a sequence of field declarations.
+
+@end itemize
-@node Miscellaneous VM Requirements, , JNI Implementation, Top
+@node Miscellaneous VM Requirements, , JVMTI Implementation, Top
@comment node-name, next, previous, up
@chapter Miscellaneous VM Requirements
diff --git a/doc/www.gnu.org/announce/20060809.wml b/doc/www.gnu.org/announce/20060809.wml
new file mode 100644
index 000000000..680e3cd4e
--- /dev/null
+++ b/doc/www.gnu.org/announce/20060809.wml
@@ -0,0 +1,225 @@
+#!wml --include=..
+
+#use wml::std::page
+#use wml::std::lang
+#use wml::fmt::isolatin
+#use wml::std::case global=upper
+
+<lang:star:slice:>
+
+<set-var last-modified-author="mjw">
+
+#include <include/macros.wml>
+
+<header title="GNU Classpath 0.92 Announcement (2006-08-09)">
+<pre>
+We are proud to announce the release of GNU Classpath 0.92 Bling! Bling!
+
+This is the first release that has a full graphics 2D implemenation
+based on Cairo enabled by default. This enables the use of applications
+like JEdit, FlickrBackup and JFreeChart out of the box. Screenshots of
+CairoGraphics2D in action http://www.jfree.org/jfreechart/samples-gnu.html
+
+Also new in this release is the inclusion of an applet viewer
+and plugin that can be embedded in webbrowsers or other applications.
+It works on any platform supported by the various runtimes based on
+GNU Classpath, including 64 bit architectures.
+
+Some other highlights in this release (more extensive list below):
+
+ An alternative awt peer implementation based on Escher that uses the
+ X protocol directly. Various ImageIO providers for png, gif and bmp
+ images. Support for reading and writing midi files and reading .au
+ and .wav files have been added. Various tools and support classes
+ have been added for jar, native2ascii, serialver, keytool, jarsigner.
+ A GConf based util.peers backend has been added. Support for using
+ alternative root certificate authorities with the security and crypto
+ packages. Start of javax.management and runtime lang.managment support.
+ NIO channels now support scatter-gather operations.
+
+GNU Classpath, essential libraries for java, is a project to create
+free core class libraries for use with runtimes, compilers and tools
+for the java programming language.
+
+The GNU Classpath developer snapshot releases are not directly aimed
+at the end user but are meant to be integrated into larger development
+platforms. For example the GCC (gcj) and Kaffe projects will use the
+developer snapshots as a base for future versions. More projects based
+on GNU Classpath: http://www.gnu.org/software/classpath/stories.html
+
+Also released is classpath-generics-0.92 an experimental branch with
+support for all the new 1.5 language features such as generics and
+enumerations. ECJ, JamVM, IKVM and Cacao are known to support the
+generics release. And you can use it to run Eclipse 3.1 with it to
+develop programs that use the new 1.5 language and core library
+additions. classpath-generics is a work in progress and not as
+extensively tested as our regular releases. But please try it out if
+you want to help us test the new 1.5 support of the core libraries.
+
+The GNU Classpath developers site http://developer.classpath.org/
+provides detailed information on how to start with helping the GNU
+Classpath project and gives an overview of the core class library
+packages currently provided. For each snapshot release generated
+documentation is provided through the GNU Classpath Tools gjdoc
+project. A documentation generation framework for java source
+files used by the GNU project. Full documentation on the currently
+implementated packages and classes can be found at:
+http://developer.classpath.org/doc/
+
+For more information about the project see also:
+
+- GNU Classpath home page:
+ http://www.gnu.org/software/classpath/
+
+- Developer information (wiki):
+ http://developer.classpath.org/
+
+- Full class documentation
+ http://developer.classpath.org/doc/
+
+- GNU Classpath hackers:
+ http://planet.classpath.org/
+
+- Autobuilder, current build status, build snapshots:
+ http://builder.classpath.org/
+
+- Application test pages (wiki)
+ http://developer.classpath.org/mediation/Applets
+ http://developer.classpath.org/mediation/FreeAWTTestApps
+ http://developer.classpath.org/mediation/FreeSwingTestApps
+ http://developer.classpath.org/mediation/FreeSWTTestApps
+
+- GNU Classpath hacking with Eclipse (wiki)
+ http://developer.classpath.org/mediation/ClasspathHackingWithEclipse
+
+- GNU Classpath promotion banners:
+ http://developer.classpath.org/mediation/ClasspathBanners
+
+GNU Classpath 0.92 can be downloaded from
+ftp://ftp.gnu.org/pub/gnu/classpath/
+or one of the ftp.gnu.org mirrors
+http://www.gnu.org/order/ftp.html
+
+File: classpath-0.92.tar.gz
+MD5sum: 4603ef3e593713d94788b919bc0b6c75
+SHA1sum: fab3d6d360f6e9d712fc999f3f085e9f9c8c641a
+
+File: classpath-0.92-generics.tar.gz (EXPERIMENTAL)
+MD5sum: 3efacbefe0224dfe57d9049619095b32
+SHA1sum: 7db4d90e36e40ec676ac813f300265849e36e223
+
+New in release 0.92 (Aug 9, 2006)
+(See the ChangeLog file for a full list of changes.)
+
+* libjawtgnu.so has been renamed libjawt.so for binary compatibility.
+ libjawt.so should be installed in a VM-specific directory rather
+ than directly in /usr/lib. Proprietary VMs put their libjawt.so
+ implementations in VM-specific directories but search /usr/lib first.
+ If GNU Classpath's libjawt.so is installed in /usr/lib it will create
+ problems for people who use a proprietary VM to run AWT Native
+ Interface applications.
+* The GdkGraphics2D backend has been made the default. There is no
+ longer an explicit dependency on Cairo, the --enable-gtk-cairo
+ configure option is gone, and GTK 2.8 or higher is now required to
+ build the GTK peers.
+* A Mozilla plugin, 'gcjwebplugin', is now included. It introduces a
+ dependency on the Mozilla plugin support headers and libraries.
+* New java implementations of png and gif imageio readers and writers.
+* A tools.texinfo document has been created and now includes
+ documentation about:
+ * appletviewer
+ * gcjwebplugin
+ * jarsigner
+ * keytool
+* Several new tools are now included:
+ * appletviewer
+ * jar
+ * native2ascii
+ * serialver
+ * keytool
+ * jarsigner
+ A new configure option --enable-tool-wrappers causes wrapper
+ binaries to be built for VMs that support the JNI Invocation API.
+* javax.sound.midi providers have been added to read and
+ write standard MIDI files.
+* A javax.sound.sampled .au and .wav file readers have been added.
+* New Java Virtual Machine Tool Interface header, jvmti.h.
+* AWT peers for X Windows based on Escher (a pure java X protocol
+ implementation) have been added. So far it supports AWT 1.1 style
+ Graphics, image loading via ImageIO (PNG, GIF and BMP images in this
+ release), top level components as well as mouse and keyboard input.
+ It is capable of running many Swing applications. Graphics2D and
+ AWT widgets are not yet supported with this peer set.
+* GConf based util.peers backend (see the --enable-gconf-peer and
+ --enable-default-preferences-peer configure options).
+* Support for batch importing trusted certificates for use with ssl
+ connections (see script/import-cacerts.sh).
+* NIO scatter-gather channel support.
+
+Runtime interface changes:
+
+* A new class, VMURLConnection, is used to implement
+ URLConnection.guessContentTypeFromStream. The reference
+ implementation uses libmagic (and falls back to doing nothing if
+ libmagic is not available).
+* The method gnu.java.io.PlatformHelper.toCanonicalForm() has been
+ replaced with a JNI implementation of VMFile.toCanonicalForm() for
+ GNU/Posix systems.
+* A new class, VMRuntimeMXBeanImpl, is used to implement
+ the low-level support of the runtime management bean.
+ VMs should use it to supply the input arguments and start
+ time of the VM. In addition, one of sun.boot.class.path
+ or java.boot.class.path should be defined by the VM to
+ support the optional boot class path access functionality.
+* The Unsafe class was moved back to the place expected by the JSR 166
+ reference implementation. We've also added a couple other new VM
+ classes to support the JSR 166 code -- sun.reflect.Reflection and
+ sun.reflect.misc.ReflectUtil.
+* Another new class, VMClassLoadingMXBeanImpl, is used to implement
+ the low-level support of the class loading management bean.
+ VMs need to supply it with information about how many classes
+ are currently loaded, how many have been unloaded and whether
+ verbose class loading output is on or off. Provision should also
+ be made for the latter to be toggled at runtime.
+* VMThreadMXBeanImpl is used to implement the low-level support
+ of the thread management bean. Providing this interface requires
+ providing a fair amount of information about threads, including
+ optional time and contention monitoring, and instances of the
+ new ThreadInfo class in java.lang.management. getState() has also
+ been added to the VMThread interface; this is required by the bean
+ as well as java.lang.Thread.
+* VMMemoryMXBeanImpl is used to implement the low-level support
+ of the memory management bean. Providing this interface requires
+ providing information about the levels of heap and non-heap memory,
+ and the number of objects eligible for garbage collection.
+* VMCompilationMXBeanImpl is used to allow for optional compilation
+ time support for Just-In-Time compilers.
+* VMMemoryPoolMXBeanImpl is used to implement the low-level support
+ of the memory pool beans. Providing this interface requires
+ providing memory usage statistics for each supported bean.
+* VMManagementFactory provides the names of the memory pools,
+ memory managers and garbage collectors maintained by the virtual
+ machine. These are used to create the beans by the ManagementFactory.
+* VMMemoryManagerMXBeanImpl and VMGarbageCollectorMXBeanImpl provide
+ low-level support for memory managers (including the specific subclass
+ of garbage collecting memory managers). The interfaces for these
+ require no more than enumerating the number of collections and the
+ time spent (for garbage collectors) and a relationship to the memory
+ pools (for all), along with a validity check.
+
+The following people helped with this release:
+
+Andreas Tobler, Andrew John Hughes, Anthony Balkissoon, Anthony Green,
+Archie Cobbs, Audrius Meskauskas, Carsten Neumann, Casey Marshall,
+Chris Burdess, Christian Thalinger, C. Scott Marshall, Dalibor Topic,
+David Gilbert, Francis Kung, Gary Benson, Henrik Gulbrandsen, Ingo
+Proetel, Ito Kazumitsu, Jeroen Frijters, Jim Huang, Kazuya Ujihara,
+Keith Seitz, Kyle Galloway, Lillian Angel, Mario Torre, Mark Wielaard,
+Martin Platter, Matthew Burgess, Matthew Wringe, Matt Wringe, Michael
+Barker, Miriam Schuster, Olivier Jolly, Paul Jenner, Raif S. Naffah,
+Robert Schuster, Roman Kennke, Sven de Marothy, Tania Bento, Thomas
+Fitzsimmons, Thomas Minor, Tom Tromey and Vivek Lakshmanan
+
+We would also like to thank the numerous bug reporters and testers!
+</pre>
+<footer>
diff --git a/doc/www.gnu.org/downloads/downloads.wml b/doc/www.gnu.org/downloads/downloads.wml
index 838783472..a6b6c1c28 100644
--- a/doc/www.gnu.org/downloads/downloads.wml
+++ b/doc/www.gnu.org/downloads/downloads.wml
@@ -77,10 +77,10 @@ sub mylink {
<download-block>
<download
- date="15 May 2006"
- version="0.91"
- url="ftp://ftp.gnu.org/gnu/classpath/classpath-0.91.tar.gz"
- notes="http://www.gnu.org/software/classpath/announce/20060515.html"
+ date="09 Aug 2006"
+ version="0.92"
+ url="ftp://ftp.gnu.org/gnu/classpath/classpath-0.92.tar.gz"
+ notes="http://www.gnu.org/software/classpath/announce/20060809.html"
>
<!-- download
@@ -100,6 +100,12 @@ sub mylink {
<download-block>
<download
+ date="15 May 2006"
+ version="0.91"
+ url="ftp://ftp.gnu.org/gnu/classpath/classpath-0.91.tar.gz"
+ notes="http://www.gnu.org/software/classpath/announce/20060515.html"
+>
+<download
date="06 March 2006"
version="0.90"
url="ftp://ftp.gnu.org/gnu/classpath/classpath-0.90.tar.gz"
diff --git a/doc/www.gnu.org/newsitems.txt b/doc/www.gnu.org/newsitems.txt
index df0066500..5d5184ac4 100644
--- a/doc/www.gnu.org/newsitems.txt
+++ b/doc/www.gnu.org/newsitems.txt
@@ -1,3 +1,8 @@
+<newsitem date="09 Aug 2006">
+<createlink name="GNU Classpath 0.92"
+ url="announce/20060809.html">
+</newsitem>
+
<newsitem date="15 May 2006">
<createlink name="GNU Classpath 0.91"
url="announce/20060515.html">
diff --git a/examples/.cvsignore b/examples/.cvsignore
index 56910f344..d79d635e8 100644
--- a/examples/.cvsignore
+++ b/examples/.cvsignore
@@ -2,3 +2,5 @@ Makefile
Makefile.in
examples.zip
Makefile.jawt
+Makefile.java2d
+
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 71909e8d6..84e3ebe0f 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -23,8 +23,9 @@ endif
# All our example java source files
EXAMPLE_JAVA_FILES = $(srcdir)/gnu/classpath/examples/*/*.java $(srcdir)/gnu/classpath/examples/*/*/*.java $(srcdir)/gnu/classpath/examples/*/*/*/*.java
-# The example C source files
+# The example C source & header files
EXAMPLE_C_FILES = $(srcdir)/gnu/classpath/examples/*/*.c
+EXAMPLE_CH_FILES = $(srcdir)/gnu/classpath/examples/*/*.h
# The zip files with classes we want to produce.
EXAMPLE_ZIP = examples.zip
@@ -39,7 +40,7 @@ EXAMPLE_ICONS = $(srcdir)/gnu/classpath/examples/icons/*.png
READMES = $(srcdir)/gnu/classpath/examples/CORBA/swing/README.html
# All the files we find "interesting"
-ALL_EXAMPLE_FILES = $(EXAMPLE_JAVA_FILES) $(EXAMPLE_C_FILES) $(EXAMPLE_ICONS) $(READMES)
+ALL_EXAMPLE_FILES = $(EXAMPLE_JAVA_FILES) $(EXAMPLE_C_FILES) $(EXAMPLE_CH_FILES) $(EXAMPLE_ICONS) $(READMES)
# Some architecture independent data to be installed.
example_DATA = $(EXAMPLE_ZIP) README
@@ -62,7 +63,9 @@ install-data-local:
$(INSTALL_DATA) $$file $(DESTDIR)$(pkgdatadir)/examples/$$f; \
done
echo "$(INSTALL_DATA) Makefile.jawt $(DESTDIR)$(pkgdatadir)/examples/"
+ echo "$(INSTALL_DATA) Makefile.java2d $(DESTDIR)$(pkgdatadir)/examples/"
$(INSTALL_DATA) Makefile.jawt $(DESTDIR)$(pkgdatadir)/examples/
+ $(INSTALL_DATA) Makefile.java2d $(DESTDIR)$(pkgdatadir)/examples/
uninstall-local:
srcdir_cnt=`echo $(srcdir) | wc -c`; \
@@ -72,10 +75,12 @@ uninstall-local:
rm -f $(DESTDIR)$(pkgdatadir)/examples/$$f; \
done
echo "rm -f $(DESTDIR)$(pkgdatadir)/examples/Makefile.jawt"
+ echo "rm -f $(DESTDIR)$(pkgdatadir)/examples/Makefile.java2d"
rm -f $(DESTDIR)$(pkgdatadir)/examples/Makefile.jawt
+ rm -f $(DESTDIR)$(pkgdatadir)/examples/Makefile.java2d
# Make sure everything is included in the distribution.
-EXTRA_DIST = README Makefile.jawt.in
+EXTRA_DIST = README Makefile.jawt.in Makefile.java2d.in
dist-hook:
srcdir_cnt=`echo $(srcdir) | wc -c`; \
for file in $(ALL_EXAMPLE_FILES); do \
diff --git a/examples/Makefile.java2d.in b/examples/Makefile.java2d.in
new file mode 100644
index 000000000..dac22068c
--- /dev/null
+++ b/examples/Makefile.java2d.in
@@ -0,0 +1,17 @@
+# @configure_input@
+
+srcdir = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+includedir = @includedir@
+libdir = @libdir@
+pkglibdir = $(libdir)/@PACKAGE@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+
+all: $(srcdir)/gnu/classpath/examples/java2d/bench.c $(srcdir)/gnu/classpath/examples/java2d/bench.h
+ gcc -g -O0 -Wall -I$(srcdir)/gnu/classpath/examples/java2d $(GTK_CFLAGS) -L$(GTK_LIBS) \
+ -o cairobench $(srcdir)/gnu/classpath/examples/java2d/bench.c
+
+clean:
+ rm -f gnu/classpath/examples/java2d/bench
diff --git a/examples/README b/examples/README
index 727677363..f7bf59962 100644
--- a/examples/README
+++ b/examples/README
@@ -46,6 +46,23 @@ You can then run the example as follows:
export LD_LIBRARY_PATH=.:/usr/local/classpath/lib/classpath
jamvm gnu.classpath.examples.jawt.DemoJAWT
+The java2d benchmarking demos include a GTK widget to measure the native
+speed of some basic java2d options, without the JNI overhead.
+
+You can invoke it with:
+
+ make -f Makefile.java2d
+
+Or you can compile by hand as follows:
+
+ gcc -g -O0 -Wall -I./gnu/classpath/examples/java2d \
+ -o cairobench gnu/classpath/examples/java2d/bench.c \
+ `pkg-config --libs --cflags gtk+-2.0`
+
+You can then run the example as follows:
+
+ ./cairobench
+
All example code is distributed under the GNU General Public License (GPL).
The example icons used in some of the examples come from gnome-icon-theme
diff --git a/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/StructureToPassHelper.java b/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/StructureToPassHelper.java
index c41ebe237..652ee53cc 100644
--- a/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/StructureToPassHelper.java
+++ b/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/StructureToPassHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package gnu.classpath.examples.CORBA.SimpleCommunication.communication;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.ORB;
import org.omg.CORBA.StructMember;
import org.omg.CORBA.TypeCode;
@@ -81,13 +83,14 @@ public abstract class StructureToPassHelper
*/
public static synchronized TypeCode type()
{
- StructMember[] members = new StructMember[ 2 ];
+ StructMember[] members = new StructMember[2];
TypeCode member = null;
- member = ORB.init().create_string_tc(0);
- members [ 0 ] = new StructMember("a", member, null);
- member = ORB.init().create_string_tc(0);
- members [ 1 ] = new StructMember("b", member, null);
- return ORB.init().create_struct_tc(StructureToPassHelper.id(), "StructureToPass", members);
+ member = OrbRestricted.Singleton.create_string_tc(0);
+ members[0] = new StructMember("a", member, null);
+ member = OrbRestricted.Singleton.create_string_tc(0);
+ members[1] = new StructMember("b", member, null);
+ return OrbRestricted.Singleton.create_struct_tc(StructureToPassHelper.id(),
+ "StructureToPass", members);
}
/**
diff --git a/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/StructureToReturnHelper.java b/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/StructureToReturnHelper.java
index 42fb7a574..2ac03a895 100644
--- a/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/StructureToReturnHelper.java
+++ b/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/StructureToReturnHelper.java
@@ -37,6 +37,8 @@ exception statement from your version. */
package gnu.classpath.examples.CORBA.SimpleCommunication.communication;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.ORB;
import org.omg.CORBA.StructMember;
import org.omg.CORBA.TCKind;
@@ -86,17 +88,18 @@ public abstract class StructureToReturnHelper
*/
public static synchronized TypeCode type()
{
- StructMember[] members = new StructMember[ 3 ];
- TypeCode member = ORB.init().get_primitive_tc(TCKind.tk_long);
- members [ 0 ] = new StructMember("n", member, null);
- member = ORB.init().create_string_tc(0);
- members [ 1 ] = new StructMember("c", member, null);
- member = ORB.init().get_primitive_tc(TCKind.tk_long);
- member = ORB.init().create_array_tc(3, member);
- members [ 2 ] = new StructMember("arra", member, null);
- return ORB.init().create_struct_tc(StructureToReturnHelper.id(), "StructureToReturn",
- members
- );
+ StructMember[] members = new StructMember[3];
+ TypeCode member = OrbRestricted.Singleton.get_primitive_tc(TCKind.tk_long);
+ members[0] = new StructMember("n", member, null);
+ member = OrbRestricted.Singleton.create_string_tc(0);
+ members[1] = new StructMember("c", member, null);
+ member = OrbRestricted.Singleton.get_primitive_tc(TCKind.tk_long);
+ member = OrbRestricted.Singleton.create_array_tc(3, member);
+ members[2] = new StructMember("arra", member, null);
+ return OrbRestricted.Singleton.create_struct_tc(
+ StructureToReturnHelper.id(),
+ "StructureToReturn",
+ members);
}
/**
diff --git a/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/TreeNodeHelper.java b/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/TreeNodeHelper.java
index f111d0eac..ccf792da8 100644
--- a/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/TreeNodeHelper.java
+++ b/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/TreeNodeHelper.java
@@ -38,6 +38,9 @@ exception statement from your version. */
package gnu.classpath.examples.CORBA.SimpleCommunication.communication;
+
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.ORB;
import org.omg.CORBA.StructMember;
@@ -128,18 +131,18 @@ public abstract class TreeNodeHelper
// To avoid the infinite recursion loop, the
// recursive reference is handled in specific way.
if (active)
- return ORB.init().create_recursive_tc(_id);
+ return OrbRestricted.Singleton.create_recursive_tc(_id);
active = true;
// List all memebers of the TreeNode structure.
StructMember[] members = new StructMember[ 2 ];
TypeCode memberType;
- memberType = ORB.init().create_string_tc(0);
+ memberType = OrbRestricted.Singleton.create_string_tc(0);
members [ 0 ] = new StructMember("name", memberType, null);
- memberType = ORB.init().create_recursive_tc("");
+ memberType = OrbRestricted.Singleton.create_recursive_tc("");
members [ 1 ] = new StructMember("children", memberType, null);
typeCode =
- ORB.init().create_struct_tc(TreeNodeHelper.id(), "TreeNode", members);
+ OrbRestricted.Singleton.create_struct_tc(TreeNodeHelper.id(), "TreeNode", members);
active = false;
}
}
diff --git a/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/WeThrowThisExceptionHelper.java b/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/WeThrowThisExceptionHelper.java
index 4d5eee74b..6ad13a9bb 100644
--- a/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/WeThrowThisExceptionHelper.java
+++ b/examples/gnu/classpath/examples/CORBA/SimpleCommunication/communication/WeThrowThisExceptionHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package gnu.classpath.examples.CORBA.SimpleCommunication.communication;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.ORB;
import org.omg.CORBA.StructMember;
@@ -96,9 +98,9 @@ public abstract class WeThrowThisExceptionHelper
{
StructMember[] members = new StructMember[ 1 ];
TypeCode member = null;
- member = ORB.init().get_primitive_tc(TCKind.tk_long);
+ member = OrbRestricted.Singleton.get_primitive_tc(TCKind.tk_long);
members [ 0 ] = new StructMember("ourField", member, null);
- return ORB.init().create_struct_tc(WeThrowThisExceptionHelper.id(),
+ return OrbRestricted.Singleton.create_struct_tc(WeThrowThisExceptionHelper.id(),
"WeThrowThisException", members
);
}
diff --git a/examples/gnu/classpath/examples/awt/Demo.java b/examples/gnu/classpath/examples/awt/Demo.java
index 5e668dde6..bd5e755cb 100644
--- a/examples/gnu/classpath/examples/awt/Demo.java
+++ b/examples/gnu/classpath/examples/awt/Demo.java
@@ -20,11 +20,70 @@ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
package gnu.classpath.examples.awt;
-import java.awt.*;
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Canvas;
+import java.awt.Checkbox;
+import java.awt.CheckboxGroup;
+import java.awt.CheckboxMenuItem;
+import java.awt.Choice;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.DisplayMode;
+import java.awt.FileDialog;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.GridLayout;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.Label;
import java.awt.List;
-import java.awt.event.*;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
+import java.awt.MenuShortcut;
+import java.awt.Panel;
+import java.awt.ScrollPane;
+import java.awt.TextField;
+import java.awt.Toolkit;
+import java.awt.Window;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragSource;
+import java.awt.dnd.DragSourceContext;
+import java.awt.dnd.DragSourceDragEvent;
+import java.awt.dnd.DragSourceDropEvent;
+import java.awt.dnd.DragSourceEvent;
+import java.awt.dnd.DragSourceListener;
+import java.awt.dnd.DropTarget;
+import java.awt.dnd.DropTargetDragEvent;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.dnd.DropTargetEvent;
+import java.awt.dnd.DropTargetListener;
+import java.awt.dnd.InvalidDnDOperationException;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
import java.net.URL;
-import java.util.*;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
class Demo
{
@@ -156,6 +215,7 @@ class Demo
addSubWindow ("Animation", new AnimationWindow ());
addSubWindow ("Resolution", new ResolutionWindow ());
addSubWindow ("Fullscreen", new FullscreenWindow ());
+ addSubWindow ("Drag n' Drop", new DragDropWindow ());
Panel sp = new Panel();
PrettyPanel p = new PrettyPanel();
@@ -799,6 +859,141 @@ class Demo
}
}
+ static class DragDropWindow
+ extends SubFrame
+ implements ActionListener, DropTargetListener
+ {
+ DragLabel source = new DragLabel("Drag and drop me to the following Button",
+ Label.CENTER);
+
+ Button target = new Button();
+
+ public void init()
+ {
+ source.setForeground(Color.red);
+ add(source, BorderLayout.NORTH);
+
+ target.addActionListener(this);
+ add(target, BorderLayout.SOUTH);
+
+ new DropTarget(target, DnDConstants.ACTION_COPY_OR_MOVE, this);
+
+ setSize(205, 100);
+
+ pack();
+ }
+
+ public void actionPerformed(ActionEvent e)
+ {
+ Button b = (Button) e.getSource();
+ b.setLabel("");
+ }
+
+ public void dragEnter(DropTargetDragEvent e)
+ {
+ }
+
+ public void dragExit(DropTargetEvent e)
+ {
+ }
+
+ public void dragOver(DropTargetDragEvent e)
+ {
+ }
+
+ public void drop(DropTargetDropEvent e)
+ {
+ try
+ {
+ Transferable t = e.getTransferable();
+
+ if (e.isDataFlavorSupported(DataFlavor.stringFlavor))
+ {
+ e.acceptDrop(e.getDropAction());
+
+ String s;
+ s = (String) t.getTransferData(DataFlavor.stringFlavor);
+
+ target.setLabel(s);
+
+ e.dropComplete(true);
+ }
+ else
+ e.rejectDrop();
+ }
+ catch (java.io.IOException e2)
+ {
+ }
+ catch (UnsupportedFlavorException e2)
+ {
+ }
+ }
+
+ public void dropActionChanged(DropTargetDragEvent e)
+ {
+ }
+
+ class DragLabel
+ extends Label
+ implements DragGestureListener, DragSourceListener
+ {
+ private DragSource ds = DragSource.getDefaultDragSource();
+
+ public DragLabel(String s, int alignment)
+ {
+ super(s, alignment);
+ int action = DnDConstants.ACTION_COPY_OR_MOVE;
+ ds.createDefaultDragGestureRecognizer(this, action, this);
+ }
+
+ public void dragGestureRecognized(DragGestureEvent e)
+ {
+ try
+ {
+ Transferable t = new StringSelection(getText());
+ e.startDrag(DragSource.DefaultCopyNoDrop, t, this);
+ }
+ catch (InvalidDnDOperationException e2)
+ {
+ System.out.println(e2);
+ }
+ }
+
+ public void dragDropEnd(DragSourceDropEvent e)
+ {
+ if (e.getDropSuccess() == false)
+ return;
+
+ int action = e.getDropAction();
+ if ((action & DnDConstants.ACTION_MOVE) != 0)
+ setText("");
+ }
+
+ public void dragEnter(DragSourceDragEvent e)
+ {
+ DragSourceContext ctx = e.getDragSourceContext();
+
+ int action = e.getDropAction();
+ if ((action & DnDConstants.ACTION_COPY) != 0)
+ ctx.setCursor(DragSource.DefaultCopyDrop);
+ else
+ ctx.setCursor(DragSource.DefaultCopyNoDrop);
+ }
+
+ public void dragExit(DragSourceEvent e)
+ {
+ }
+
+ public void dragOver(DragSourceDragEvent e)
+ {
+ }
+
+ public void dropActionChanged(DragSourceDragEvent e)
+ {
+ }
+ }
+ }
+
static class FullscreenWindow extends SubFrame
{
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
diff --git a/examples/gnu/classpath/examples/java2d/bench.c b/examples/gnu/classpath/examples/java2d/bench.c
new file mode 100644
index 000000000..e5b45aa1c
--- /dev/null
+++ b/examples/gnu/classpath/examples/java2d/bench.c
@@ -0,0 +1,606 @@
+/* bench.c -- native benchmark for Cairo library (meant to test java2d)
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath examples.
+
+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. */
+
+#include "bench.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <sys/timeb.h>
+
+G_DEFINE_TYPE (Benchmark, benchmark, GTK_TYPE_DRAWING_AREA);
+
+// Needed for the gtk widget, but not used:
+static void
+benchmark_class_init (BenchmarkClass *klass)
+{
+}
+
+static void
+benchmark_init (Benchmark *obj)
+{
+}
+
+// The Arc2D's PathIterator uses some transforms, so we condense the required
+// functionality of AffineTransform
+static void
+doTransform (double rx, double ry, double theta, double *cvec)
+{
+ // Define identity matrix (corresponds to new AffineTransform())
+ double m00 = 1;
+ double m10 = 0;
+ double m01 = 0;
+ double m11 = 1;
+ double m02 = 0;
+ double m12 = 0;
+
+ // AffineTransform.scale(rx, ry)
+ m00 = m00 * rx;
+ m01 = m01 * ry;
+ m10 = m10 * rx;
+ m11 = m11 * ry;
+
+ // AffineTransform.rotate(theta)
+ double c = cos(theta);
+ double s = sin(theta);
+ double n00 = m00 * c + m01 * s;
+ double n01 = m00 * -s + m01 * c;
+ double n10 = m10 * c + m11 * s;
+ double n11 = m10 * -s + m11 * c;
+
+ m00 = n00;
+ m01 = n01;
+ m10 = n10;
+ m11 = n11;
+
+ // AffineTransform.transform(cvec, 0, cvec, 0, 1)
+ double dstPts[2];
+ dstPts[0] = (float) (m00 * cvec[0] + m01 * cvec[1] + m02);
+ dstPts[1] = (float) (m10 * cvec[0] + m11 * cvec[1] + m12);
+ cvec[0] = dstPts[0];
+ cvec[1] = dstPts[1];
+}
+
+// Place an arc on the cairo path, simulating java2d's Arc2D
+static void
+setupArc(cairo_t *cr, GtkWidget *bench, int shift)
+{
+ double x, y;
+
+ // Normally passed into the Arc2D constructor
+ x = bench->allocation.x + (rand() % (bench->allocation.width - minSize + 1));
+ y = bench->allocation.y + (rand() % (bench->allocation.height - minSize + 1));
+
+ int angle = rand() % 360;
+ int length = (rand() % 360) - angle;
+ int width = rand() % (int)((bench->allocation.width - x - 10) + 10);
+ int height = rand() % (int)((bench->allocation.height - y - 10) + 10);
+
+ // This is from the ArcPath iterator
+ double start = angle * (M_PI / 180);
+ double extent = length * (M_PI / 180);
+
+ if (extent < 0)
+ {
+ extent = -extent;
+ start = 2 * M_PI - extent + start;
+ }
+
+ int limit;
+ if (width < 0 || height < 0) // We assume type == 0; ie, Arc2D.OPEN
+ limit = -1;
+ else if (extent == 0)
+ limit = 0;
+ else if (extent <= M_PI / 2.0)
+ limit = 1;
+ else if (extent <= M_PI)
+ limit = 2;
+ else if (extent <= 3.0 * (M_PI / 2.0))
+ limit = 3;
+ else
+ limit = 4;
+
+ // This is from CairoGraphics2D.walkPath
+ double xnew = 0;
+ double ynew = 0;
+ double coords[6];
+
+ cairo_fill_rule_t cfillrule = CAIRO_FILL_RULE_WINDING;
+ cairo_set_fill_rule(cr, cfillrule);
+
+ // First iteration will move to the starting point
+ double rx = width / 2;
+ double ry = height / 2;
+ double xmid = x + rx;
+ double ymid = y + ry;
+ coords[0] = xmid + rx * cos(start);
+ coords[1] = ymid - ry * sin(start);
+
+ if (shift == 1)
+ {
+ xnew = floor(coords[0]) + 0.5;
+ ynew = floor(coords[1]) + 0.5;
+ }
+ else
+ {
+ xnew = coords[0];
+ ynew = coords[1];
+ }
+
+ cairo_move_to(cr, xnew, ynew);
+
+ // Iterate through segments of the arc
+ int current;
+ for (current = 1; current <= limit; current++)
+ {
+ // Back to the ArcPath iterator's getCurrent
+ double kappa = (sqrt(2.0) - 1.0) * (4.0 / 3.0);
+ double quad = (M_PI / 2.0);
+
+ double curr_begin = start + (current - 1) * quad;
+ double curr_extent;
+
+ if (start + extent - curr_begin < quad)
+ curr_extent = (start + extent) - curr_begin;
+ else
+ curr_extent = quad;
+
+ double portion_of_a_quadrant = curr_extent / quad;
+
+ double x0 = xmid + rx * cos(curr_begin);
+ double y0 = ymid - ry * sin(curr_begin);
+
+ double x1 = xmid + rx * cos(curr_begin + curr_extent);
+ double y1 = ymid - ry * sin(curr_begin + curr_extent);
+
+ double cvec[2];
+ double len = kappa * portion_of_a_quadrant;
+ double angle = curr_begin;
+
+ cvec[0] = 0;
+ cvec[1] = len;
+ doTransform(rx, ry, angle, cvec);
+ coords[0] = x0 + cvec[0];
+ coords[1] = y0 - cvec[1];
+
+ cvec[0] = 0;
+ cvec[1] = -len;
+ doTransform(rx, ry, angle, cvec);
+ doTransform(1, 1, curr_extent, cvec);
+ coords[2] = x1 + cvec[0];
+ coords[3] = y1 - cvec[1];
+
+ coords[4] = x1;
+ coords[5] = y1;
+
+ // draw it, from CairoGraphics2D.walkPath
+ if (shift == 1)
+ {
+ xnew = floor(coords[4]) + 0.5;
+ ynew = floor(coords[5]) + 0.5;
+ cairo_curve_to(cr, floor(coords[0]) + 0.5, floor(coords[1]) + 0.5,
+ floor(coords[2]) + 0.5, floor(coords[3]) + 0.5,
+ xnew, ynew);
+ }
+ else
+ {
+ xnew = coords[4];
+ ynew = coords[5];
+ cairo_curve_to(cr, coords[0], coords[1], coords[2],
+ coords[3], xnew, ynew);
+ }
+ }
+
+ // Randomize the colour, just for asthetics =)
+ cairo_set_source_rgb(cr, (rand() % 100 / (float)100),
+ (rand() % 100 / (float)100),
+ (rand() % 100 / (float)100));
+
+}
+
+// Place a beizer curve on the cairo path, simulating java2d's CubicCurve2D
+static void
+setupCurve(cairo_t *cr, GtkWidget *bench, int shift)
+{
+ // These are options when creating a new curve
+ int x1 = bench->allocation.x + (rand() % (bench->allocation.width - minSize));
+ int y1 = bench->allocation.y + (rand() % (bench->allocation.height - minSize));
+ int xc1 = bench->allocation.x + (rand() % (bench->allocation.width - minSize));
+ int yc1 = bench->allocation.y + (rand() % (bench->allocation.height - minSize));
+ int xc2 = bench->allocation.x + (rand() % (bench->allocation.width - minSize));
+ int yc2 = bench->allocation.y + (rand() % (bench->allocation.height - minSize));
+ int x2 = bench->allocation.x + (rand() % (bench->allocation.width - minSize));
+ int y2 = bench->allocation.y + (rand() % (bench->allocation.height - minSize));
+
+ // From CairoGraphics2D.walkPath
+ double xnew = 0;
+ double ynew = 0;
+ double coords[6];
+
+ cairo_fill_rule_t cfillrule = CAIRO_FILL_RULE_WINDING;
+ cairo_set_fill_rule(cr, cfillrule);
+
+ // And into CubicCurve's PathIterator...
+ // start by moving to the starting coordinate
+ coords[0] = (float) x1;
+ coords[1] = (float) y1;
+
+ if (shift == 1)
+ {
+ xnew = floor(coords[0]) + 0.5;
+ ynew = floor(coords[1]) + 0.5;
+ }
+ else
+ {
+ xnew = coords[0];
+ ynew = coords[1];
+ }
+
+ cairo_move_to(cr, xnew, ynew);
+
+ // Now the curve itself
+ coords[0] = (float) xc1;
+ coords[1] = (float) yc1;
+ coords[2] = (float) xc2;
+ coords[3] = (float) yc2;
+ coords[4] = (float) x2;
+ coords[5] = (float) y2;
+
+ if (shift == 1)
+ {
+ xnew = floor(coords[4]) + 0.5;
+ ynew = floor(coords[5]) + 0.5;
+ cairo_curve_to(cr, floor(coords[0]) + 0.5, floor(coords[1]) + 0.5,
+ floor(coords[2]) + 0.5, floor(coords[3]) + 0.5,
+ xnew, ynew);
+ }
+ else
+ {
+ xnew = coords[4];
+ ynew = coords[5];
+ cairo_curve_to(cr, coords[0], coords[1], coords[2],
+ coords[3], xnew, ynew);
+ }
+
+ // Randomize colour for asthetics
+ cairo_set_source_rgb(cr, (rand() % 100 / (float)100),
+ (rand() % 100 / (float)100),
+ (rand() % 100 / (float)100));
+}
+
+// Place a line on the cairo path, simulating java2d's Line2D
+static void
+setupLine(cairo_t *cr, GtkWidget *bench, int shift)
+{
+ // These are set when you create a line
+ int x1 = bench->allocation.x + (rand() % (bench->allocation.width - minSize));
+ int y1 = bench->allocation.y + (rand() % (bench->allocation.height - minSize));
+ int x2 = bench->allocation.x + (rand() % (bench->allocation.width - minSize));
+ int y2 = bench->allocation.y + (rand() % (bench->allocation.height - minSize));
+
+ // This is from CairoGraphics2D.walkPath
+ double xnew = 0;
+ double ynew = 0;
+ double coords[6];
+
+ cairo_fill_rule_t cfillrule = CAIRO_FILL_RULE_WINDING;
+ cairo_set_fill_rule(cr, cfillrule);
+
+ // And into Line2D's PathIterator
+ coords[0] = (float) x1;
+ coords[1] = (float) y1;
+
+ if (shift == 1)
+ {
+ xnew = floor(coords[0]) + 0.5;
+ ynew = floor(coords[1]) + 0.5;
+ }
+ else
+ {
+ xnew = coords[0];
+ ynew = coords[1];
+ }
+
+ cairo_move_to(cr, xnew, ynew);
+
+ coords[0] = (float) x2;
+ coords[1] = (float) y2;
+
+ if (shift == 1)
+ {
+ xnew = floor(coords[0]) + 0.5;
+ ynew = floor(coords[1]) + 0.5;
+ }
+ else
+ {
+ xnew = coords[0];
+ ynew = coords[1];
+ }
+
+ cairo_line_to(cr, xnew, ynew);
+
+ // Randomize colour for asthetics
+ cairo_set_source_rgb(cr, (rand() % 100 / (float)100),
+ (rand() % 100 / (float)100),
+ (rand() % 100 / (float)100));
+}
+
+// Place a rectangle on the cairo path, simulating java2d's Rectangle2D
+static void
+setupRect(cairo_t *cr, GtkWidget *bench, int shift)
+{
+ // These are set when you create a rectangle
+ int x1 = bench->allocation.x + (rand() % (bench->allocation.width - minSize));
+ int y1 = bench->allocation.y + (rand() % (bench->allocation.height - minSize));
+ int x2 = bench->allocation.x + (rand() % (bench->allocation.width - minSize));
+ int y2 = bench->allocation.y + (rand() % (bench->allocation.height - minSize));
+
+ // draw() and fill() have been optimized to ignore the PathIterator.
+ // We do the same here.
+ double xnew = 0;
+ double ynew = 0;
+
+ if (shift == 1)
+ {
+ xnew = floor(x1) + 0.5;
+ ynew = floor(y1) + 0.5;
+ }
+ else
+ {
+ xnew = x1;
+ ynew = y1;
+ }
+
+ cairo_rectangle(cr, x1, y1, x2, y2);
+
+ // Randomize colour for asthetics
+ cairo_set_source_rgb(cr, (rand() % 100 / (float)100),
+ (rand() % 100 / (float)100),
+ (rand() % 100 / (float)100));
+}
+
+// The real work gets done here: this function is called when the widget
+// is drawn on screen.
+static void
+draw (GtkWidget *bench, cairo_t *cr)
+{
+ // Setup
+ struct timeb t1, t2;
+ int i, timeElapsed;
+
+ cairo_set_line_width(cr, lineWidth);
+
+ if (antialias == 0)
+ cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
+ else
+ cairo_set_antialias(cr, CAIRO_ANTIALIAS_GRAY);
+
+ // Tell the user what's going on
+ printf("Testing native cairo drawing..\n");
+ printf(" Screen size is %d x %d \n", screenWidth, screenHeight);
+ printf(" Line width is %d\n", lineWidth);
+ printf(" Test size: %d\n", testSize);
+
+ if (antialias == 0)
+ printf(" Anti-alias is off\n");
+ else
+ printf(" Anti-alias is on\n");
+
+ printf("\n");
+ fflush(stdout);
+
+ // Draw & fill Arc
+ if (arcTest == 1)
+ {
+ // Draw
+ ftime(&t1);
+ for (i = 0; i < testSize; i++)
+ {
+ setupArc(cr, bench, 1);
+ cairo_stroke (cr);
+ }
+
+ ftime(&t2);
+ timeElapsed = 1000 * (t2.time - t1.time) + (t2.millitm - t1.millitm);
+ printf("Draw arc: %d ms\n", timeElapsed);
+ fflush(stdout);
+
+ // Fill
+ ftime(&t1);
+ for (i = 0; i < testSize; i++)
+ {
+ setupArc(cr, bench, 0);
+ cairo_fill (cr);
+ }
+
+ ftime(&t2);
+ timeElapsed = 1000 * (t2.time - t1.time) + (t2.millitm - t1.millitm);
+ printf("Fill arc: %d ms\n", timeElapsed);
+ }
+
+ // Draw cubic curve
+ if (curveTest == 1)
+ {
+ ftime(&t1);
+ for (i = 0; i < testSize; i++)
+ {
+ setupCurve(cr, bench, 1);
+ cairo_stroke (cr);
+ }
+
+ ftime(&t2);
+ timeElapsed = 1000 * (t2.time - t1.time) + (t2.millitm - t1.millitm);
+ printf("Draw cubic curve: %d ms\n", timeElapsed);
+ }
+
+ // Ellipse: skip; this is just a special case of arc
+ // General path: skip; this doesn't even work in java2d
+
+ // Draw Line
+ if (lineTest == 1)
+ {
+ ftime(&t1);
+ for (i = 0; i < testSize; i++)
+ {
+ setupLine(cr, bench, 1);
+ cairo_stroke (cr);
+ }
+
+ ftime(&t2);
+ timeElapsed = 1000 * (t2.time - t1.time) + (t2.millitm - t1.millitm);
+ printf("Draw line: %d ms\n", timeElapsed);
+ }
+
+ // Draw & fill Rectangle
+ if (rectTest == 1)
+ {
+ // Draw
+ ftime(&t1);
+ for (i = 0; i < testSize; i++)
+ {
+ setupRect(cr, bench, 1);
+ cairo_stroke (cr);
+ }
+
+ ftime(&t2);
+ timeElapsed = 1000 * (t2.time - t1.time) + (t2.millitm - t1.millitm);
+ printf("Draw rectangle: %d ms\n", timeElapsed);
+
+ // Fill
+ ftime(&t1);
+ for (i = 0; i < testSize; i++)
+ {
+ setupRect(cr, bench, 0);
+ cairo_fill (cr);
+ }
+
+ ftime(&t2);
+ timeElapsed = 1000 * (t2.time - t1.time) + (t2.millitm - t1.millitm);
+ printf("Fill rectangle: %d ms\n", timeElapsed);
+ }
+
+ // Round rectangle: skip, it's just a combination of lines and curves
+ // Image: skip?
+
+ printf("\n");
+}
+
+GtkWidget *
+benchmark_new (void)
+{
+ return g_object_new (BENCHMARK_TYPE, NULL);
+}
+
+int
+main (int argc, char **argv)
+{
+ // Set defaults
+ minSize = 10;
+ arcTest = 0;
+ curveTest = 0;
+ lineTest = 0;
+ rectTest = 0;
+ screenWidth = 320;
+ screenHeight = 240;
+ testSize = 1000;
+ antialias = 0;
+ lineWidth = 1;
+
+ // Process any command-line user options
+ int i;
+ for (i = 1; i < argc; i++)
+ {
+ // Process options first
+ if (!strcmp(argv[i], "-a"))
+ antialias = 1;
+ else if (!strcmp(argv[i], "-h"))
+ screenHeight = atoi(argv[++i]);
+ else if (!strcmp(argv[i], "-l"))
+ lineWidth = atoi(argv[++i]);
+ else if (!strcmp(argv[i], "-t"))
+ testSize = atoi(argv[++i]);
+ else if (!strcmp(argv[i], "-w"))
+ screenWidth = atoi(argv[++i]);
+ else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--h")
+ || !strcmp(argv[i], "-help") || !strcmp(argv[i], "--help"))
+ {
+ printf("Cairo benchmarker, meant to measure JNI overhead\n");
+ printf("Usage: bench [-a] [-h height] [-t test size] [-w width] [tests...]\n");
+ printf("\n");
+ printf(" Valid options: -a turn on anti-aliasing (default off)\n");
+ printf(" -h set screen height (default 240)\n");
+ printf(" -l set stroke line width (default 1)\n");
+ printf(" -t set test size (default 1000)\n");
+ printf(" -w set screen width (default 320)\n");
+ printf(" -h | --help\n");
+ printf(" Valid tests: arc\n");
+ printf(" curve\n");
+ printf(" line\n");
+ printf(" rect\n");
+ printf(" (default: run all)\n");
+ exit (0);
+ }
+
+ // Process tests
+ else if (!strcmp(argv[i], "arc"))
+ arcTest = 1;
+ else if (!strcmp(argv[i], "curve"))
+ curveTest = 1;
+ else if (!strcmp(argv[i], "line"))
+ lineTest = 1;
+ else if (!strcmp(argv[i], "rect"))
+ rectTest = 1;
+ }
+
+ // If no tests were specified, we default to running all of them
+ if (arcTest == 0 && curveTest == 0 && lineTest == 0 && rectTest == 0)
+ {
+ arcTest = 1;
+ curveTest = 1;
+ lineTest = 1;
+ rectTest = 1;
+ }
+
+ // Set up gtk widget
+ GtkWidget *window, *bench;
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_resize(GTK_WINDOW(window), screenWidth, screenHeight);
+ gtk_window_set_title(GTK_WINDOW(window), "cairo benchmark");
+
+ // Set up benchmkar and cairo surface
+ bench = benchmark_new ();
+ gtk_container_add (GTK_CONTAINER (window), bench);
+ gtk_widget_show_all (window);
+
+ cairo_t *cr;
+ cr = gdk_cairo_create (bench->window);
+
+ // Run tests
+ draw (bench, cr);
+
+ // Hold output on screen until user exits.
+ printf("Press any key to exit.\n");
+ getchar();
+ exit(0);
+gtk_main();
+}
diff --git a/examples/gnu/classpath/examples/java2d/bench.h b/examples/gnu/classpath/examples/java2d/bench.h
new file mode 100644
index 000000000..aebd50a67
--- /dev/null
+++ b/examples/gnu/classpath/examples/java2d/bench.h
@@ -0,0 +1,64 @@
+/* bench.h -- native benchmark for Cairo library (meant to test java2d)
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath examples.
+
+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. */
+
+#ifndef __BENCH_H__
+#define __BENCH_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define BENCHMARK_TYPE (benchmark_get_type())
+#define BENCHMARK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj, BENCHMARK_TYPE, Benchmark)
+#define BENCHMARK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BENCHMARK_TYPE, BenchmarkClass);
+#define IS_BENCHMARK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BENCHMARK_TYPE))
+#define IS_BENCHMARK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BENCHMARK_TYPE))
+#define BENCHMARK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BENCHMARK_TYPE, BenchmarkClass))
+
+typedef struct _Benchmark Benchmark;
+typedef struct _BenchmarkClass BenchmarkClass;
+
+struct _Benchmark {
+ GtkDrawingArea parent;
+
+};
+
+struct _BenchmarkClass {
+ GtkDrawingAreaClass parent_class;
+};
+
+GType benchmark_get_type (void);
+GtkWidget *benchmark_new (void);
+
+static int minSize;
+static int antialias;
+static int arcTest;
+static int curveTest;
+static int lineTest;
+static int rectTest;
+
+static int screenHeight;
+static int screenWidth;
+static int testSize;
+static int lineWidth;
+
+G_END_DECLS
+
+#endif
diff --git a/examples/gnu/classpath/examples/management/TestBeans.java b/examples/gnu/classpath/examples/management/TestBeans.java
new file mode 100644
index 000000000..ad8234555
--- /dev/null
+++ b/examples/gnu/classpath/examples/management/TestBeans.java
@@ -0,0 +1,55 @@
+/* TestBeans.java -- Tests the dynamic interface of the beans.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath examples.
+
+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. */
+
+package gnu.classpath.examples.management;
+
+import java.lang.management.ManagementFactory;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.management.DynamicMBean;
+
+public class TestBeans
+{
+ public static void main(String[] args)
+ throws Exception
+ {
+ List beans = new ArrayList();
+ /* FIXME: When there's a server, this will be easier... :) */
+ beans.add(ManagementFactory.getOperatingSystemMXBean());
+ beans.add(ManagementFactory.getRuntimeMXBean());
+ beans.add(ManagementFactory.getThreadMXBean());
+ beans.add(ManagementFactory.getCompilationMXBean());
+ beans.add(ManagementFactory.getClassLoadingMXBean());
+ beans.add(ManagementFactory.getMemoryMXBean());
+ beans.addAll(ManagementFactory.getMemoryPoolMXBeans());
+ beans.addAll(ManagementFactory.getMemoryManagerMXBeans());
+ beans.addAll(ManagementFactory.getGarbageCollectorMXBeans());
+ Iterator it = beans.iterator();
+ while (it.hasNext())
+ {
+ DynamicMBean bean = (DynamicMBean) it.next();
+ if (bean != null)
+ System.out.println(bean.getMBeanInfo());
+ }
+ }
+}
diff --git a/examples/gnu/classpath/examples/swing/Demo.java b/examples/gnu/classpath/examples/swing/Demo.java
index ad20fec7e..19bc27c1d 100644
--- a/examples/gnu/classpath/examples/swing/Demo.java
+++ b/examples/gnu/classpath/examples/swing/Demo.java
@@ -30,6 +30,7 @@ import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
+import javax.swing.plaf.basic.BasicLookAndFeel;
import javax.swing.plaf.metal.DefaultMetalTheme;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.metal.MetalTheme;
@@ -192,6 +193,10 @@ public class Demo
}
});
+ // Installs the BasicLookAndFeel.
+ UIManager.installLookAndFeel("(Basic Look And Feel)",
+ InstantiableBasicLookAndFeel.class.getName());
+
// Create L&F menu.
JMenu lafMenu = new JMenu("Look and Feel");
ButtonGroup lafGroup = new ButtonGroup();
@@ -662,10 +667,45 @@ public class Demo
{
ex.printStackTrace();
}
+
SwingUtilities.updateComponentTreeUI(frame);
themesMenu.setEnabled(laf.getClassName()
.equals("javax.swing.plaf.metal.MetalLookAndFeel"));
}
+ }
+ /**
+ * An implementation of BasicLookAndFeel which can be instantiated.
+ *
+ * @author Robert Schuster (robertschuster@fsfe.org)
+ *
+ */
+ public static class InstantiableBasicLookAndFeel extends BasicLookAndFeel
+ {
+ public String getDescription()
+ {
+ return "An instantiable implementation of BasicLookAndFeel";
+ }
+
+ public String getID()
+ {
+ return "instantiableBasicLookAndFeel";
+ }
+
+ public String getName()
+ {
+ return "Instantiable Basic Look And Feel";
+ }
+
+ public boolean isNativeLookAndFeel()
+ {
+ return false;
+ }
+
+ public boolean isSupportedLookAndFeel()
+ {
+ return true;
+ }
}
+
}
diff --git a/examples/gnu/classpath/examples/swing/HtmlDemo.java b/examples/gnu/classpath/examples/swing/HtmlDemo.java
index 988b0bd0e..223ee07cd 100644
--- a/examples/gnu/classpath/examples/swing/HtmlDemo.java
+++ b/examples/gnu/classpath/examples/swing/HtmlDemo.java
@@ -52,6 +52,8 @@ import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
+import javax.swing.text.Element;
+import javax.swing.text.html.HTMLDocument;
/**
* Parses and displays HTML content.
@@ -63,14 +65,17 @@ public class HtmlDemo extends JPanel
JTextPane html = new JTextPane();
- JTextArea text = new JTextArea("<html><body><p>" +
+ JTextArea text = new JTextArea("<html><body>" +
"123456789HR!<hr>987654321"+
"123456789BR!<br>987654321"+
+ "<p id='insertHere'>Insertion target</p><p>"+
"<font color=red>ma</font>"+
"<sup>sup</sup>normal<sub>sub</sub>normal</p><p>Table:"+
"<table><tr>a<td>b<td>c<tr>x<td>y<td>z</table></body></html>");
JPanel buttons;
+
+ int n;
public HtmlDemo()
{
@@ -111,7 +116,131 @@ public class HtmlDemo extends JPanel
});
buttons.add(parse);
+
+ JButton insertBeforeEnd = new JButton("before end");
+ insertBeforeEnd.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent event)
+ {
+ HTMLDocument doc = (HTMLDocument) html.getDocument();
+ Element el = doc.getElement("insertHere");
+ System.out.println("Element found:"+el);
+ try
+ {
+ doc.insertBeforeEnd(el,"before end "+(n++));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ JButton insertBeforeStart = new JButton("before start");
+ insertBeforeStart.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent event)
+ {
+ HTMLDocument doc = (HTMLDocument) html.getDocument();
+ Element el = doc.getElement("insertHere");
+ System.out.println("Element found:"+el);
+ try
+ {
+ doc.insertBeforeStart(el,"before start "+(n++));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ JButton insertAfterEnd = new JButton("after end");
+ insertAfterEnd.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent event)
+ {
+ HTMLDocument doc = (HTMLDocument) html.getDocument();
+ Element el = doc.getElement("insertHere");
+ System.out.println("Element found:"+el);
+ try
+ {
+ doc.insertAfterEnd(el,"after end "+(n++));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ JButton insertAfterStart = new JButton("after start");
+ insertAfterStart.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent event)
+ {
+ HTMLDocument doc = (HTMLDocument) html.getDocument();
+ Element el = doc.getElement("insertHere");
+ System.out.println("Element found:"+el);
+ try
+ {
+ doc.insertAfterStart(el,"after start "+(n++));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ });
+
+
+ JButton setInner = new JButton("inner");
+ setInner.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent event)
+ {
+ HTMLDocument doc = (HTMLDocument) html.getDocument();
+ Element el = doc.getElement("insertHere");
+ System.out.println("Element found:"+el);
+ try
+ {
+ doc.setInnerHTML(el,"inner "+(n++));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ JButton setOuter = new JButton("outer");
+ setOuter.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent event)
+ {
+ HTMLDocument doc = (HTMLDocument) html.getDocument();
+ Element el = doc.getElement("insertHere");
+ System.out.println("Element found:"+el);
+ try
+ {
+ doc.setOuterHTML(el,"outer "+(n++));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ buttons.add(insertBeforeStart);
+ buttons.add(insertAfterStart);
+ buttons.add(insertBeforeEnd);
+ buttons.add(insertAfterEnd);
+
+ buttons.add(setInner);
+ buttons.add(setOuter);
+
add(center, BorderLayout.CENTER);
add(buttons, BorderLayout.SOUTH);
}
@@ -144,7 +273,7 @@ public class HtmlDemo extends JPanel
JFrame frame = new JFrame();
frame.getContentPane().add(demo);
- frame.setSize(new Dimension(640, 480));
+ frame.setSize(new Dimension(700, 480));
frame.setVisible(true);
}
});
diff --git a/gnu/CORBA/Connected_objects.java b/gnu/CORBA/Connected_objects.java
index ce5761007..53ef2dd17 100644
--- a/gnu/CORBA/Connected_objects.java
+++ b/gnu/CORBA/Connected_objects.java
@@ -242,4 +242,14 @@ public class Connected_objects
free_object_number++;
return instance_number;
}
+
+ /**
+ * Get the number of the connected objects.
+ *
+ * @return the size of the internal map.
+ */
+ public int size()
+ {
+ return objects.size();
+ }
} \ No newline at end of file
diff --git a/gnu/CORBA/ForwardRequestHelper.java b/gnu/CORBA/ForwardRequestHelper.java
index cbdf46f25..5b77fa030 100644
--- a/gnu/CORBA/ForwardRequestHelper.java
+++ b/gnu/CORBA/ForwardRequestHelper.java
@@ -62,11 +62,6 @@ import org.omg.PortableServer.ForwardRequest;
public abstract class ForwardRequestHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the ForwardRequest from given Any.
* This method uses the ForwardRequestHolder.
*
@@ -132,18 +127,14 @@ public abstract class ForwardRequestHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 1 ];
-
- TypeCode field;
-
- field = ObjectHelper.type();
- members [ 0 ] = new StructMember("forward_reference", field, null);
- typeCode = orb.create_exception_tc(id(), "ForwardRequest", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[ 1 ];
+
+ TypeCode field;
+
+ field = ObjectHelper.type();
+ members [ 0 ] = new StructMember("forward_reference", field, null);
+ return orb.create_exception_tc(id(), "ForwardRequest", members);
}
/**
diff --git a/gnu/CORBA/OrbFunctional.java b/gnu/CORBA/OrbFunctional.java
index 7b9c34ada..9695fdc82 100644
--- a/gnu/CORBA/OrbFunctional.java
+++ b/gnu/CORBA/OrbFunctional.java
@@ -1775,4 +1775,14 @@ public class OrbFunctional extends OrbRestricted
running = false;
super.finalize();
}
+
+ /**
+ * Get the number of objects that are connected to this ORB.
+ *
+ * @return the number of objects, connected to this ORB.
+ */
+ public int countConnectedObjects()
+ {
+ return connected_objects.size();
+ }
} \ No newline at end of file
diff --git a/gnu/classpath/debug/Simple1LineFormatter.java b/gnu/classpath/debug/Simple1LineFormatter.java
index a95f8a9d2..96573193a 100644
--- a/gnu/classpath/debug/Simple1LineFormatter.java
+++ b/gnu/classpath/debug/Simple1LineFormatter.java
@@ -38,10 +38,11 @@ exception statement from your version. */
package gnu.classpath.debug;
-import gnu.classpath.SystemProperties;
+import gnu.java.security.action.GetPropertyAction;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.security.AccessController;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
@@ -94,8 +95,8 @@ public class Simple1LineFormatter
private static final String THREAD_PATTERN = " #########0;-#########0";
private static final String SPACES_32 = " ";
private static final String SPACES_6 = " ";
- private static final String LS = SystemProperties.getProperty("line.separator");
-
+ private static final String LS = (String) AccessController.doPrivileged
+ (new GetPropertyAction("line.separator"));
private DateFormat dateFormat;
private NumberFormat threadFormat;
diff --git a/gnu/classpath/debug/SystemLogger.java b/gnu/classpath/debug/SystemLogger.java
index 94aa93f69..502b48870 100644
--- a/gnu/classpath/debug/SystemLogger.java
+++ b/gnu/classpath/debug/SystemLogger.java
@@ -38,7 +38,9 @@ version. */
package gnu.classpath.debug;
-import gnu.classpath.SystemProperties;
+import gnu.java.security.action.GetPropertyAction;
+
+import java.security.AccessController;
import java.util.StringTokenizer;
import java.util.logging.Logger;
@@ -49,8 +51,8 @@ public final class SystemLogger
static
{
SYSTEM.setFilter (PreciseFilter.GLOBAL);
-
- String defaults = SystemProperties.getProperty ("gnu.classpath.debug.components");
+ String defaults = (String) AccessController.doPrivileged
+ (new GetPropertyAction("gnu.classpath.debug.components"));
if (defaults != null)
{
diff --git a/gnu/classpath/jdwp/event/ExceptionEvent.java b/gnu/classpath/jdwp/event/ExceptionEvent.java
index a51e69c8f..1303c09be 100644
--- a/gnu/classpath/jdwp/event/ExceptionEvent.java
+++ b/gnu/classpath/jdwp/event/ExceptionEvent.java
@@ -70,6 +70,9 @@ public class ExceptionEvent
//the location where the exception was caught
private Location _catchLocation;
+
+ //the class where the exeption was thrown
+ private Class _klass;
/**
* Constructs a new <code>ExceptionEvent</code> where the exception was
@@ -82,13 +85,14 @@ public class ExceptionEvent
* @param instance the instance that threw the exception
*/
public ExceptionEvent(Throwable exception, Thread thread, Location location,
- Location catchLocation, Object instance)
+ Location catchLocation, Class clazz, Object instance)
{
super(JdwpConstants.EventKind.EXCEPTION);
_exception = exception;
_thread = thread;
_location = location;
_catchLocation = catchLocation;
+ _klass = clazz;
_instance = instance;
}
@@ -108,17 +112,28 @@ public class ExceptionEvent
else if (type == EVENT_INSTANCE)
return _instance;
else if (type == EVENT_CLASS)
- return _instance.getClass();
+ return _klass;
else if (type == EVENT_EXCEPTION_CLASS)
return _exception.getClass();
else if (type == EVENT_EXCEPTION_CAUGHT)
- if (_catchLocation != null)
+ if (_catchLocation.getMethod() != null)
return new Boolean(true);
else
return new Boolean(false);
return null;
}
+
+ /**
+ * Sets the catchLocation, used for exceptions that are caught in different
+ * stack frames from where they are thrown.
+ *
+ * @param catchLoc the location of the catch
+ */
+ public void setCatchLoc(Location catchLoc)
+ {
+ _catchLocation = catchLoc;
+ }
/**
* Writes the event to the given stream
@@ -136,9 +151,7 @@ public class ExceptionEvent
tid.write(outStream);
_location.write(outStream);
oid.writeTagged(outStream);
- if(_catchLocation != null)
- _catchLocation.write(outStream);
- else
- outStream.write(0);
+ _catchLocation.write(outStream);
+
}
}
diff --git a/gnu/classpath/jdwp/util/Location.java b/gnu/classpath/jdwp/util/Location.java
index 005b12c2b..89e81e563 100644
--- a/gnu/classpath/jdwp/util/Location.java
+++ b/gnu/classpath/jdwp/util/Location.java
@@ -94,18 +94,40 @@ public class Location
* @param os stream to write to
* @throws IOException when an error occurs writing to the stream
*/
- public void write(DataOutputStream os)
+ public void write(DataOutputStream os)
throws IOException
{
- VMIdManager idm = VMIdManager.getDefault();
- ClassReferenceTypeId crti = (ClassReferenceTypeId)
- idm.getReferenceTypeId(method.getDeclaringClass());
-
- crti.writeTagged(os);
- method.writeId(os);
- os.writeLong(index);
+ // check if this is an empty location
+ if (method != null)
+ {
+ VMIdManager idm = VMIdManager.getDefault();
+ ClassReferenceTypeId crti =
+ (ClassReferenceTypeId)
+ idm.getReferenceTypeId(method.getDeclaringClass());
+
+ crti.writeTagged(os);
+ method.writeId(os);
+ os.writeLong(index);
+ }
+ else
+ {
+ os.writeByte(1);
+ os.writeLong((long) 0);
+ os.writeLong((long) 0);
+ os.writeLong((long) 0);
+ }
}
-
+
+ /**
+ * Sets up an empty location
+ *
+ * @return new Location (setup as empty)
+ */
+ public static Location getEmptyLocation()
+ {
+ return new Location(null, 0);
+ }
+
/**
* Gets the method of this location
*
diff --git a/gnu/java/awt/ClasspathToolkit.java b/gnu/java/awt/ClasspathToolkit.java
index 5f093b71b..968cc3b16 100644
--- a/gnu/java/awt/ClasspathToolkit.java
+++ b/gnu/java/awt/ClasspathToolkit.java
@@ -1,5 +1,5 @@
/* ClasspathToolkit.java -- Abstract superclass for Classpath toolkits.
- Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -52,6 +52,7 @@ import java.awt.FontMetrics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
+import java.awt.Point;
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.image.ColorModel;
@@ -188,6 +189,9 @@ public abstract class ClasspathToolkit
*/
public abstract Font createFont(int format, InputStream stream);
+ /**
+ * Creates a RobotPeer on a given GraphicsDevice.
+ */
public abstract RobotPeer createRobot (GraphicsDevice screen)
throws AWTException;
@@ -201,8 +205,24 @@ public abstract class ClasspathToolkit
/**
* Used to register ImageIO SPIs provided by the toolkit.
+ *
+ * Our default implementation does nothing.
*/
public void registerImageIOSpis(IIORegistry reg)
{
}
+
+ /**
+ * Returns the number of mouse buttons.
+ * (used by java.awt.MouseInfo).
+ *
+ * This dummy implementation returns -1 (no mouse).
+ * toolkit implementors should overload this method if possible.
+ * @since 1.5
+ */
+ public int getMouseNumberOfButtons()
+ {
+ return -1;
+ }
}
+
diff --git a/gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java b/gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java
index 889f258fb..1f0c3ad2d 100644
--- a/gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java
+++ b/gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java
@@ -39,7 +39,8 @@ exception statement from your version. */
package gnu.java.awt.dnd;
import java.awt.Component;
-import java.awt.dnd.DragGestureEvent;
+import java.awt.Point;
+import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.MouseDragGestureRecognizer;
@@ -48,63 +49,124 @@ import java.awt.event.MouseEvent;
public class GtkMouseDragGestureRecognizer
extends MouseDragGestureRecognizer
{
+
+ public GtkMouseDragGestureRecognizer (DragSource ds)
+ {
+ this(ds, null, 0, null);
+ }
+
+ public GtkMouseDragGestureRecognizer (DragSource ds, Component c)
+ {
+ this (ds, c, 0, null);
+ }
- DragSource ds;
- Component c;
- int actions;
- DragGestureListener dgl;
-
- GtkMouseDragGestureRecognizer()
+ public GtkMouseDragGestureRecognizer (DragSource ds, Component c, int act)
{
- super(null);
+ this(ds, c, act, null);
}
public GtkMouseDragGestureRecognizer (DragSource ds, Component c, int act,
DragGestureListener dgl)
{
- super (ds, c, act, dgl);
-
- registerListeners();
-
- this.ds = ds;
- this.c = c;
- this.actions = act;
- this.dgl = dgl;
+ super(ds, c, act, dgl);
+ }
+
+ public void registerListeners ()
+ {
+ super.registerListeners();
+ }
+
+ public void unregisterListeners ()
+ {
+ super.unregisterListeners();
}
public void mouseClicked (MouseEvent e)
{
- // FIXME: Not Implemented
+ // Nothing to do here.
}
public void mousePressed (MouseEvent e)
{
- // FIXME: Not Implemented
+ events.clear();
+ if (getDropActionFromEvent(e) != DnDConstants.ACTION_NONE)
+ appendEvent(e);
}
public void mouseReleased (MouseEvent e)
{
- // FIXME: Not Implemented
+ events.clear();
}
public void mouseEntered (MouseEvent e)
{
- // FIXME: Not Implemented
+ events.clear();
}
- public void mouseExited (MouseEvent e)
+ public void mouseExited(MouseEvent e)
{
- // FIXME: Not Implemented
+ if (!events.isEmpty())
+ if (getDropActionFromEvent(e) == DnDConstants.ACTION_NONE)
+ events.clear();
}
public void mouseDragged(MouseEvent e)
{
- dgl.dragGestureRecognized(new DragGestureEvent(this, actions, e.getPoint(),
- events));
+ if (!events.isEmpty())
+ {
+ int act = getDropActionFromEvent(e);
+
+ if (act == DnDConstants.ACTION_NONE)
+ return;
+
+ Point origin = ((MouseEvent) events.get(0)).getPoint();
+ Point current = e.getPoint();
+ int dx = Math.abs(origin.x - current.x);
+ int dy = Math.abs(origin.y - current.y);
+ int threshold = DragSource.getDragThreshold();
+
+ if (dx > threshold || dy > threshold)
+ fireDragGestureRecognized(act, origin);
+ else
+ appendEvent(e);
+ }
}
-
+
public void mouseMoved (MouseEvent e)
{
- // FIXME: Not Implemented
+ // Nothing to do here.
+ }
+
+ private int getDropActionFromEvent(MouseEvent e)
+ {
+ int modEx = e.getModifiersEx();
+ int buttons = modEx & (MouseEvent.BUTTON1_DOWN_MASK
+ | MouseEvent.BUTTON2_DOWN_MASK | MouseEvent.BUTTON3_DOWN_MASK);
+ if (!(buttons == MouseEvent.BUTTON1_DOWN_MASK ||
+ buttons == MouseEvent.BUTTON2_DOWN_MASK))
+ return DnDConstants.ACTION_NONE;
+
+ // Convert modifier to a drop action
+ int sourceActions = getSourceActions();
+ int mod = modEx
+ & (MouseEvent.SHIFT_DOWN_MASK | MouseEvent.CTRL_DOWN_MASK);
+ switch (mod)
+ {
+ case MouseEvent.SHIFT_DOWN_MASK | MouseEvent.CTRL_DOWN_MASK:
+ return DnDConstants.ACTION_LINK & sourceActions;
+ case MouseEvent.CTRL_DOWN_MASK:
+ return DnDConstants.ACTION_COPY & sourceActions;
+ case MouseEvent.SHIFT_DOWN_MASK:
+ return DnDConstants.ACTION_MOVE & sourceActions;
+ default:
+ if ((sourceActions & DnDConstants.ACTION_MOVE) != 0)
+ return DnDConstants.ACTION_MOVE & sourceActions;
+ else if ((sourceActions & DnDConstants.ACTION_COPY) != 0)
+ return DnDConstants.ACTION_COPY & sourceActions;
+ else if ((sourceActions & DnDConstants.ACTION_LINK) != 0)
+ return DnDConstants.ACTION_LINK & sourceActions;
+ }
+
+ return DnDConstants.ACTION_NONE & sourceActions;
}
}
diff --git a/gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java b/gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java
index 873027290..b68fa1058 100644
--- a/gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java
+++ b/gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java
@@ -38,44 +38,147 @@ exception statement from your version. */
package gnu.java.awt.dnd.peer.gtk;
+import gnu.java.awt.peer.gtk.GtkGenericPeer;
+
+import java.awt.Component;
import java.awt.Cursor;
import java.awt.Image;
import java.awt.Point;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragSourceContext;
+import java.awt.dnd.DragSourceDragEvent;
+import java.awt.dnd.DragSourceDropEvent;
+import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.InvalidDnDOperationException;
import java.awt.dnd.peer.DragSourceContextPeer;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.LightweightPeer;
public class GtkDragSourceContextPeer
+ extends GtkGenericPeer
implements DragSourceContextPeer
{
-
- private DragGestureEvent dge;
+ private ComponentPeer peer;
+ private Cursor cursor;
+ private DragSourceContext context;
+ public static Component target;
+
+ native void nativeStartDrag(Image i, int x, int y, int action, String target);
+ native void connectSignals(ComponentPeer comp);
+ native void create(ComponentPeer comp);
+ native void nativeSetCursor(int cursor);
+ native void setTarget(GtkDropTargetContextPeer target);
public GtkDragSourceContextPeer(DragGestureEvent e)
{
- dge = e;
+ super(e.getComponent());
+ Component comp = e.getComponent();
+ peer = getComponentPeer(comp);
+
+ create(peer);
+ connectSignals(peer);
+ cursor = comp.getCursor();
+
+ // FIXME: Where do we set the target?
+
+ if ((target != null))
+ setTarget(new GtkDropTargetContextPeer(target));
+ }
+
+ ComponentPeer getComponentPeer(Component c)
+ {
+ if (c == null)
+ return null;
+
+ Component curr = c;
+ while (curr.getPeer() instanceof LightweightPeer)
+ curr = curr.getParent();
+
+ if (curr != null)
+ return curr.getPeer();
+ return null;
}
public void startDrag(DragSourceContext context, Cursor c, Image i, Point p)
throws InvalidDnDOperationException
- {
- // FIXME: Not Implemented
+ {
+ this.context = context;
+
+ if (p == null)
+ p = new Point();
+
+ // FIXME: use proper DataFlavor, not "text/plain".
+ // Also, add check to determine if dragging.
+
+ setCursor(c);
+ nativeStartDrag(i, p.x, p.y, context.getTrigger().getDragAction(),
+ "text/plain");
}
public Cursor getCursor()
{
- // FIXME: Not Implemented
- return null;
+ return cursor;
}
public void setCursor(Cursor c) throws InvalidDnDOperationException
{
- // FIXME: Not Implemented
+ if (c != null)
+ {
+ nativeSetCursor(c.getType());
+ cursor = c;
+ }
}
public void transferablesFlavorsChanged()
{
- // FIXME: Not Implemented
+ // Nothing to do here.
+ }
+
+ /**
+ * Called from native code.
+ */
+
+ public void dragEnter(int action, int modifiers)
+ {
+ context.dragEnter(new DragSourceDragEvent(context, action,
+ action
+ & context.getSourceActions(),
+ modifiers));
+ }
+
+ public void dragExit(int action, int x, int y)
+ {
+ context.dragExit(new DragSourceEvent(context, x, y));
+ }
+
+ public void dragDropEnd(int action, boolean success, int x, int y)
+ {
+ context.dragDropEnd(new DragSourceDropEvent(context, action, success, x, y));
+ }
+
+ public void dragMouseMoved(int action, int modifiers)
+ {
+ context.dragMouseMoved(new DragSourceDragEvent(context,
+ action,
+ action
+ & context.getSourceActions(),
+ modifiers));
+ }
+
+ public void dragOver(int action, int modifiers)
+ {
+ context.dragOver(new DragSourceDragEvent(context, action,
+ action
+ & context.getSourceActions(),
+ modifiers));
+ }
+
+ public void dragActionChanged(int newAction, int modifiers)
+ {
+ context.dropActionChanged(new DragSourceDragEvent(context,
+ newAction,
+ newAction
+ & context.getSourceActions(),
+ modifiers));
}
}
diff --git a/gnu/java/awt/dnd/peer/gtk/GtkDropTargetContextPeer.java b/gnu/java/awt/dnd/peer/gtk/GtkDropTargetContextPeer.java
index 421503e43..f24b3f39b 100644
--- a/gnu/java/awt/dnd/peer/gtk/GtkDropTargetContextPeer.java
+++ b/gnu/java/awt/dnd/peer/gtk/GtkDropTargetContextPeer.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package gnu.java.awt.dnd.peer.gtk;
+import gnu.java.awt.peer.gtk.GtkGenericPeer;
+
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DropTarget;
@@ -45,9 +47,15 @@ import java.awt.dnd.InvalidDnDOperationException;
import java.awt.dnd.peer.DropTargetContextPeer;
public class GtkDropTargetContextPeer
+ extends GtkGenericPeer
implements DropTargetContextPeer
{
-
+
+ public GtkDropTargetContextPeer(Object obj)
+ {
+ super(obj);
+ }
+
public void setTargetActions(int actions)
{
// FIXME: Not Implemented
diff --git a/gnu/java/awt/java2d/CubicSegment.java b/gnu/java/awt/java2d/CubicSegment.java
index 1e568f722..bf66be870 100644
--- a/gnu/java/awt/java2d/CubicSegment.java
+++ b/gnu/java/awt/java2d/CubicSegment.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package gnu.java.awt.java2d;
+import java.awt.geom.CubicCurve2D;
import java.awt.geom.Point2D;
/**
@@ -78,34 +79,89 @@ public class CubicSegment extends Segment
*/
public Object clone()
{
- return new CubicSegment(P1.getX(), P1.getY(), cp1.getX(), cp1.getY(),
- cp2.getX(), cp2.getY(), P2.getX(), P2.getY());
+ CubicSegment segment = null;
+
+ try
+ {
+ segment = (CubicSegment) super.clone();
+
+ segment.P1 = (Point2D) P1.clone();
+ segment.P2 = (Point2D) P2.clone();
+ segment.cp1 = (Point2D) cp1.clone();
+ segment.cp2 = (Point2D) cp2.clone();
+ }
+ catch (CloneNotSupportedException cnse)
+ {
+ InternalError ie = new InternalError();
+ ie.initCause(cnse);
+ throw ie;
+ }
+
+ return segment;
}
/**
- * Get the "top" and "bottom" segments of this segment.
- * First array element is p0 + normal, second is p0 - normal.
+ * Get the "top" and "bottom" segments of this segment. First array element is
+ * p0 + normal, second is p0 - normal.
*/
public Segment[] getDisplacedSegments(double radius)
{
+ // It is, apparently, impossible to derive a curve parallel to a bezier
+ // curve (unless it's a straight line), so we have no choice but to
+ // approximate the displaced segments. Similar to FlattenPathIterator.
+
+ Segment segmentTop = null;
+ Segment segmentBottom = null;
this.radius = radius;
- double x0 = P1.getX();
- double y0 = P1.getY();
- double x1 = cp1.getX();
- double y1 = cp1.getY();
- double x2 = cp2.getX();
- double y2 = cp2.getY();
- double x3 = P2.getX();
- double y3 = P2.getY();
- double[] p1 = normal(x0, y0, x1, y1);
- double[] p2 = normal(x2, y2, x3, y3);
-
- // FIXME: Doesn't compile.
- // return new Segment[]{s1, s2};
- return new Segment[0];
+ CubicCurve2D[] curves = new CubicCurve2D[10];
+ curves[0] = new CubicCurve2D.Double(P1.getX(), P1.getY(), cp1.getX(),
+ cp1.getY(), cp2.getX(), cp2.getY(),
+ P2.getX(), P2.getY());
+ int numCurves = 1;
+
+ // Hard-coded a recursion limit of 10 and flatness of 1... should we make
+ // this an option somewhere?
+ while (numCurves > 0)
+ {
+ // The curve is flat enough, or we've reached our recursion limit,
+ // so take the current start/end points and add it as a line segment
+ // to our final approximated curves
+ if (curves[numCurves - 1].getFlatnessSq() <= (radius / 3) || numCurves == 10)
+ {
+ Segment[] displaced = new LineSegment(
+ curves[numCurves - 1].getP1(),
+ curves[numCurves - 1].getP2()).getDisplacedSegments(radius);
+ if (segmentTop == null)
+ {
+ segmentTop = displaced[0];
+ segmentBottom = displaced[1];
+ }
+ else
+ {
+ segmentTop.add(displaced[0]);
+ segmentBottom.add(displaced[1]);
+ }
+ numCurves--;
+ }
+
+ // Otherwise, subdivide again and continue
+ else
+ {
+ CubicCurve2D left = new CubicCurve2D.Double();
+ CubicCurve2D right = new CubicCurve2D.Double();
+ curves[numCurves - 1].subdivide(left, right);
+ curves[numCurves - 1] = right;
+ curves[numCurves] = left;
+ curves[numCurves - 1] = right;
+ curves[numCurves] = left;
+ numCurves++;
+ }
+ }
+
+ return new Segment[] { segmentTop, segmentBottom };
}
-
+
public void reverse()
{
Point2D temp = P1;
@@ -116,12 +172,12 @@ public class CubicSegment extends Segment
cp2 = temp;
}
- public double[] first()
+ public double[] cp1()
{
return new double[]{cp1.getX(), cp1.getY()};
}
- public double[] last()
+ public double[] cp2()
{
return new double[]{cp2.getX(), cp2.getY()};
}
diff --git a/gnu/java/awt/java2d/LineSegment.java b/gnu/java/awt/java2d/LineSegment.java
index 9c0bcc7ea..0395fd0af 100644
--- a/gnu/java/awt/java2d/LineSegment.java
+++ b/gnu/java/awt/java2d/LineSegment.java
@@ -62,7 +62,22 @@ public class LineSegment extends Segment
*/
public Object clone()
{
- return new LineSegment(P1, P2);
+ LineSegment segment = null;
+
+ try
+ {
+ segment = (LineSegment) super.clone();
+ segment.P1 = (Point2D) P1.clone();
+ segment.P2 = (Point2D) P2.clone();
+ }
+ catch (CloneNotSupportedException cnse)
+ {
+ InternalError ie = new InternalError();
+ ie.initCause(cnse);
+ throw ie;
+ }
+
+ return segment;
}
/**
@@ -91,12 +106,12 @@ public class LineSegment extends Segment
P2 = p;
}
- public double[] first()
+ public double[] cp1()
{
return new double[]{P2.getX(), P2.getY()};
}
- public double[] last()
+ public double[] cp2()
{
return new double[]{P1.getX(), P1.getY()};
}
diff --git a/gnu/java/awt/java2d/QuadSegment.java b/gnu/java/awt/java2d/QuadSegment.java
index 9c15a8cfd..5e15fe881 100644
--- a/gnu/java/awt/java2d/QuadSegment.java
+++ b/gnu/java/awt/java2d/QuadSegment.java
@@ -88,8 +88,24 @@ public class QuadSegment extends Segment
*/
public Object clone()
{
- return new QuadSegment(P1.getX(), P1.getY(), cp.getX(), cp.getY(),
- P2.getX(), P2.getY());
+ QuadSegment segment = null;
+
+ try
+ {
+ segment = (QuadSegment) super.clone();
+
+ segment.P1 = (Point2D) P1.clone();
+ segment.P2 = (Point2D) P2.clone();
+ segment.cp = (Point2D) cp.clone();
+ }
+ catch (CloneNotSupportedException cnse)
+ {
+ InternalError ie = new InternalError();
+ ie.initCause(cnse);
+ throw ie;
+ }
+
+ return segment;
}
/**
@@ -201,12 +217,12 @@ public class QuadSegment extends Segment
P2 = p;
}
- public double[] first()
+ public double[] cp1()
{
return new double[]{cp.getX(), cp.getY()};
}
- public double[] last()
+ public double[] cp2()
{
return new double[]{cp.getX(), cp.getY()};
}
diff --git a/gnu/java/awt/java2d/Segment.java b/gnu/java/awt/java2d/Segment.java
index 9a985f696..df1f67605 100644
--- a/gnu/java/awt/java2d/Segment.java
+++ b/gnu/java/awt/java2d/Segment.java
@@ -42,24 +42,38 @@ import java.awt.geom.Point2D;
public abstract class Segment implements Cloneable
{
- // segment type, PathIterator segment types are used.
+ // Start and end points of THIS segment
public Point2D P1;
public Point2D P2;
+
+ // Segments can be linked together internally as a linked list
+ public Segment first;
public Segment next;
public Segment last;
+
+ // Half the stroke width
protected double radius;
+ /**
+ * Create a new, empty segment
+ */
public Segment()
{
P1 = P2 = null;
+ first = this;
next = null;
last = this;
}
+ /**
+ * Add a segment to the polygon
+ * @param newsegment segment to add
+ */
public void add(Segment newsegment)
{
+ newsegment.first = first;
last.next = newsegment;
- last = last.next;
+ last = last.next.last;
}
/**
@@ -68,6 +82,7 @@ public abstract class Segment implements Cloneable
public void reverseAll()
{
reverse();
+ first = last;
Segment v = next;
Segment former = this;
next = null;
@@ -91,7 +106,7 @@ public abstract class Segment implements Cloneable
/**
* Get the normal vector to the slope of the line.
- * Returns: 0.5*width*(norm of derivative of the (x0,y0)-(x1,y1) vector)
+ * @return vector of length radius, normal to the (x0,y0)-(x1,y1) vector)
*/
protected double[] normal(double x0, double y0, double x1, double y1)
{
@@ -117,6 +132,9 @@ public abstract class Segment implements Cloneable
return new double[]{ dx, dy };
}
+ /**
+ * Reverse the current segment
+ */
public abstract void reverse();
/**
@@ -125,7 +143,16 @@ public abstract class Segment implements Cloneable
*/
public abstract Segment[] getDisplacedSegments(double radius);
- public abstract double[] first();
- public abstract double[] last();
+ /**
+ * Returns the coordinates of the first control point, or the start point
+ * for a line segment.
+ */
+ public abstract double[] cp1();
+
+ /**
+ * Returns the coordinates of the second control point, or the end point
+ * for a line segment.
+ */
+ public abstract double[] cp2();
}
diff --git a/gnu/java/awt/peer/ClasspathFontPeer.java b/gnu/java/awt/peer/ClasspathFontPeer.java
index 78ab3a9de..dad7bb0b0 100644
--- a/gnu/java/awt/peer/ClasspathFontPeer.java
+++ b/gnu/java/awt/peer/ClasspathFontPeer.java
@@ -145,7 +145,8 @@ public abstract class ClasspathFontPeer
uname.equals ("SERIF") ||
uname.equals ("MONOSPACED") ||
uname.equals ("DIALOG") ||
- uname.equals ("DIALOGINPUT"));
+ uname.equals ("DIALOGINPUT") ||
+ uname.equals ("DEFAULT"));
}
protected static String logicalFontNameToFaceName (String name)
@@ -161,6 +162,8 @@ public abstract class ClasspathFontPeer
return "Helvetica";
else if (uname.equals ("DIALOGINPUT"))
return "Helvetica";
+ else if (uname.equals ("DEFAULT"))
+ return "Dialog.plain";
else
return "Helvetica";
}
@@ -233,7 +236,7 @@ public abstract class ClasspathFontPeer
family = (String) attribs.get (TextAttribute.FAMILY);
if (name == null)
- name = "SansSerif";
+ name = "Default";
if (attribs.containsKey (TextAttribute.WEIGHT))
{
diff --git a/gnu/java/awt/peer/GLightweightPeer.java b/gnu/java/awt/peer/GLightweightPeer.java
index 88733b92f..3029502ff 100644
--- a/gnu/java/awt/peer/GLightweightPeer.java
+++ b/gnu/java/awt/peer/GLightweightPeer.java
@@ -54,25 +54,14 @@ import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
import java.awt.event.PaintEvent;
import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.VolatileImage;
-import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
import java.awt.peer.LightweightPeer;
-/*
- * Another possible implementation strategy for lightweight peers is
- * to make GLightweightPeer a placeholder class that implements
- * LightweightPeer. Then the Component and Container classes could
- * identify a peer as lightweight and handle it specially. The
- * current approach is probably more clear but less efficient.
- */
-
/**
* A stub class that implements the ComponentPeer and ContainerPeer
* interfaces using callbacks into the Component and Container
@@ -85,47 +74,48 @@ import java.awt.peer.LightweightPeer;
public class GLightweightPeer
implements LightweightPeer, ContainerPeer
{
- private Component comp;
-
- private Insets containerInsets;
-
- public GLightweightPeer(Component comp)
+ public GLightweightPeer()
{
- this.comp = comp;
+ // Nothing to do here.
}
// -------- java.awt.peer.ContainerPeer implementation:
public Insets insets()
{
- return getInsets ();
+ // Nothing to do here for lightweights.
+ return null;
}
public Insets getInsets()
{
- if (containerInsets == null)
- containerInsets = new Insets (0,0,0,0);
- return containerInsets;
+ // Nothing to do here for lightweights.
+ return null;
}
public void beginValidate()
{
+ // Nothing to do here for lightweights.
}
public void endValidate()
{
+ // Nothing to do here for lightweights.
}
public void beginLayout()
{
+ // Nothing to do here for lightweights.
}
public void endLayout()
{
+ // Nothing to do here for lightweights.
}
public boolean isPaintPending()
{
+ // Nothing to do here for lightweights.
return false;
}
@@ -133,122 +123,162 @@ public class GLightweightPeer
public int checkImage(Image img, int width, int height, ImageObserver o)
{
- return comp.getToolkit().checkImage(img, width, height, o);
+ // Nothing to do here for lightweights.
+ return -1;
}
public Image createImage(ImageProducer prod)
{
- return comp.getToolkit().createImage(prod);
+ // Nothing to do here for lightweights.
+ return null;
}
/* This method is not called. */
public Image createImage(int width, int height)
{
+ // Nothing to do here for lightweights.
return null;
}
- public void disable() {}
+ public void disable()
+ {
+ // Nothing to do here for lightweights.
+ }
- public void dispose() {}
+ public void dispose()
+ {
+ // Nothing to do here for lightweights.
+ }
- public void enable() {}
+ public void enable()
+ {
+ // Nothing to do here for lightweights.
+ }
public GraphicsConfiguration getGraphicsConfiguration()
{
+ // Nothing to do here for lightweights.
return null;
}
public FontMetrics getFontMetrics(Font f)
{
- return comp.getToolkit().getFontMetrics(f);
+ // Nothing to do here for lightweights.
+ return null;
}
/* Returning null here tells the Component object that called us to
* use its parent's Graphics. */
public Graphics getGraphics()
{
+ // Nothing to do here for lightweights.
return null;
}
public Point getLocationOnScreen()
{
- Point parentLocation = comp.getParent().getLocationOnScreen();
- return new Point (parentLocation.x + comp.getX(),
- parentLocation.y + comp.getY());
+ // Nothing to do here for lightweights.
+ return null;
}
public Dimension getMinimumSize()
{
- return new Dimension(comp.getWidth(), comp.getHeight());
+ return minimumSize();
}
- /* A lightweight component's preferred size is equivalent to its
- * Component width and height values. */
public Dimension getPreferredSize()
{
- return new Dimension(comp.getWidth(), comp.getHeight());
+ return preferredSize();
}
/* Returning null here tells the Component object that called us to
* use its parent's Toolkit. */
public Toolkit getToolkit()
{
+ // Nothing to do here for lightweights.
return null;
}
- public void handleEvent(AWTEvent e) {}
+ public void handleEvent(AWTEvent e)
+ {
+ // Nothing to do here for lightweights.
+ }
- public void hide() {}
+ public void hide()
+ {
+ // Nothing to do here for lightweights.
+ }
public boolean isFocusable()
{
+ // Nothing to do here for lightweights.
return false;
}
public boolean isFocusTraversable()
{
+ // Nothing to do here for lightweights.
return false;
}
public Dimension minimumSize()
{
- return getMinimumSize();
+ return new Dimension(0, 0);
}
public Dimension preferredSize()
{
- return getPreferredSize();
+ return new Dimension(0, 0);
}
- public void paint(Graphics graphics) {}
+ public void paint(Graphics graphics)
+ {
+ // Nothing to do here for lightweights.
+ }
public boolean prepareImage(Image img, int width, int height,
ImageObserver o)
{
- return comp.getToolkit().prepareImage(img, width, height, o);
+ // Nothing to do here for lightweights.
+ return false;
}
- public void print(Graphics graphics) {}
+ public void print(Graphics graphics)
+ {
+ // Nothing to do here for lightweights.
+ }
public void repaint(long tm, int x, int y, int width, int height)
{
- Component p = comp.getParent();
- if (p != null)
- p.repaint(tm, x + comp.getX(), y + comp.getY(), width, height);
+ // Nothing to do here for lightweights.
}
- public void requestFocus() {}
+ public void requestFocus()
+ {
+ // Nothing to do here for lightweights.
+ }
- public boolean requestFocus(Component source, boolean bool1, boolean bool2, long x)
+ public boolean requestFocus(Component source, boolean bool1, boolean bool2,
+ long x)
{
+ // Nothing to do here for lightweights.
return false;
}
- public void reshape(int x, int y, int width, int height) {}
+ public void reshape(int x, int y, int width, int height)
+ {
+ // Nothing to do here for lightweights.
+ }
- public void setBackground(Color color) {}
+ public void setBackground(Color color)
+ {
+ // Nothing to do here for lightweights.
+ }
- public void setBounds(int x, int y, int width, int height) {}
+ public void setBounds(int x, int y, int width, int height)
+ {
+ // Nothing to do here for lightweights.
+ }
/**
* Sets the cursor on the heavy-weight parent peer.
@@ -256,110 +286,141 @@ public class GLightweightPeer
*/
public void setCursor(Cursor cursor)
{
- Component p = comp.getParent();
- while (p != null && p.isLightweight())
- p = p.getParent();
-
- if (p != null)
- {
- // Don't actually change the cursor of the component
- // otherwise other childs inherit this cursor.
- ComponentPeer peer = p.getPeer();
- if (peer != null)
- peer.setCursor(cursor);
- }
+ // Nothing to do here for lightweights.
}
- public void setEnabled(boolean enabled) {}
+ public void setEnabled(boolean enabled)
+ {
+ // Nothing to do here for lightweights.
+ }
- public void setEventMask(long eventMask) {}
+ public void setEventMask(long eventMask)
+ {
+ // Nothing to do here for lightweights.
+ }
- public void setFont(Font font) {}
+ public void setFont(Font font)
+ {
+ // Nothing to do here for lightweights.
+ }
- public void setForeground(Color color) {}
+ public void setForeground(Color color)
+ {
+ // Nothing to do here for lightweights.
+ }
- public void setVisible(boolean visible) {}
+ public void setVisible(boolean visible)
+ {
+ // Nothing to do here for lightweights.
+ }
- public void show() {}
+ public void show()
+ {
+ // Nothing to do here for lightweights.
+ }
- public ColorModel getColorModel ()
+ public ColorModel getColorModel()
{
- return comp.getColorModel ();
+ // Nothing to do here for lightweights.
+ return null;
}
public boolean isObscured()
{
+ // Nothing to do here for lightweights.
return false;
}
public boolean canDetermineObscurity()
{
+ // Nothing to do here for lightweights.
return false;
}
- public void coalescePaintEvent(PaintEvent e) { }
+ public void coalescePaintEvent(PaintEvent e)
+ {
+ // Nothing to do here for lightweights.
+ }
- public void updateCursorImmediately() { }
+ public void updateCursorImmediately()
+ {
+ // Nothing to do here for lightweights.
+ }
public VolatileImage createVolatileImage(int width, int height)
{
+ // Nothing to do here for lightweights.
return null;
}
public boolean handlesWheelScrolling()
{
+ // Nothing to do here for lightweights.
return false;
}
public void createBuffers(int x, BufferCapabilities capabilities)
- throws AWTException { }
+ throws AWTException
+ {
+ // Nothing to do here for lightweights.
+ }
public Image getBackBuffer()
{
+ // Nothing to do here for lightweights.
return null;
}
- public void flip(BufferCapabilities.FlipContents contents) { }
+ public void flip(BufferCapabilities.FlipContents contents)
+ {
+ // Nothing to do here for lightweights.
+ }
- public void destroyBuffers() { }
+ public void destroyBuffers()
+ {
+ // Nothing to do here for lightweights.
+ }
public boolean isRestackSupported()
{
+ // Nothing to do here for lightweights.
return false;
}
public void cancelPendingPaint(int x, int y, int width, int height)
{
-
+ // Nothing to do here for lightweights.
}
public void restack()
{
-
+ // Nothing to do here for lightweights.
}
public Rectangle getBounds()
{
+ // Nothing to do here for lightweights.
return null;
}
public void reparent(ContainerPeer parent)
{
-
+ // Nothing to do here for lightweights.
}
public void setBounds(int x, int y, int z, int width, int height)
{
-
+ // Nothing to do here for lightweights.
}
public boolean isReparentSupported()
{
- return false;
+ // Nothing to do here for lightweights.
+ return true;
}
public void layout()
{
-
+ // Nothing to do here for lightweights.
}
}
diff --git a/gnu/java/awt/peer/gtk/BufferedImageGraphics.java b/gnu/java/awt/peer/gtk/BufferedImageGraphics.java
index d9d300d91..5412cbea9 100644
--- a/gnu/java/awt/peer/gtk/BufferedImageGraphics.java
+++ b/gnu/java/awt/peer/gtk/BufferedImageGraphics.java
@@ -40,16 +40,15 @@ package gnu.java.awt.peer.gtk;
import java.awt.Color;
import java.awt.Graphics;
-import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
-import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
+import java.awt.image.Raster;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.image.ColorModel;
@@ -130,17 +129,17 @@ public class BufferedImageGraphics extends CairoGraphics2D
cairo_t = surface.newCairoContext();
- DataBuffer db = bi.getRaster().getDataBuffer();
+ Raster raster = bi.getRaster();
int[] pixels;
// get pixels
- if(db instanceof CairoSurface)
- pixels = ((CairoSurface)db).getPixels(imageWidth * imageHeight);
+ if(raster instanceof CairoSurface)
+ pixels = ((CairoSurface)raster).getPixels(imageWidth * imageHeight);
else
{
if( hasFastCM )
{
- pixels = ((DataBufferInt)db).getData();
+ pixels = ((DataBufferInt)raster.getDataBuffer()).getData();
if( !hasAlpha )
for(int i = 0; i < pixels.length; i++)
pixels[i] &= 0xFFFFFFFF;
diff --git a/gnu/java/awt/peer/gtk/CairoGraphics2D.java b/gnu/java/awt/peer/gtk/CairoGraphics2D.java
index 61871ccbc..8fe04fe77 100644
--- a/gnu/java/awt/peer/gtk/CairoGraphics2D.java
+++ b/gnu/java/awt/peer/gtk/CairoGraphics2D.java
@@ -40,8 +40,8 @@ package gnu.java.awt.peer.gtk;
import gnu.java.awt.ClasspathToolkit;
-import java.awt.AlphaComposite;
import java.awt.AWTPermission;
+import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
@@ -53,11 +53,11 @@ import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Paint;
+import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
-import java.awt.Polygon;
import java.awt.TexturePaint;
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
@@ -66,6 +66,7 @@ import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.PathIterator;
@@ -322,6 +323,11 @@ public abstract class CairoGraphics2D extends Graphics2D
* Set the current transform matrix
*/
private native void cairoSetMatrix(long pointer, double[] m);
+
+ /**
+ * Scaling method
+ */
+ private native void cairoScale(long pointer, double x, double y);
/**
* Set the compositing operator
@@ -369,6 +375,18 @@ public abstract class CairoGraphics2D extends Graphics2D
*/
private native void cairoRectangle(long pointer, double x, double y,
double width, double height);
+
+ /**
+ * Appends an arc to the current path
+ */
+ private native void cairoArc(long pointer, double x, double y,
+ double radius, double angle1, double angle2);
+
+ /**
+ * Save / restore a cairo path
+ */
+ private native void cairoSave(long pointer);
+ private native void cairoRestore(long pointer);
/**
* New current path
@@ -665,8 +683,8 @@ public abstract class CairoGraphics2D extends Graphics2D
int width = (int) tp.getAnchorRect().getWidth();
int height = (int) tp.getAnchorRect().getHeight();
- double scaleX = (width+1) / (double) img.getWidth();
- double scaleY = (height+1) / (double) img.getHeight();
+ double scaleX = width / (double) img.getWidth();
+ double scaleY = height / (double) img.getHeight();
AffineTransform at = new AffineTransform(scaleX, 0, 0, scaleY, 0, 0);
AffineTransformOp op = new AffineTransformOp(at, getRenderingHints());
@@ -903,53 +921,79 @@ public abstract class CairoGraphics2D extends Graphics2D
public void draw(Shape s)
{
if ((stroke != null && ! (stroke instanceof BasicStroke))
- || (comp instanceof AlphaComposite
- && ((AlphaComposite) comp).getAlpha() != 1.0))
+ || (comp instanceof AlphaComposite && ((AlphaComposite) comp).getAlpha() != 1.0))
{
- // FIXME: This is a hack to work around BasicStrokes's current
- // limitations wrt cubic curves.
- // See CubicSegment.getDisplacedSegments().
- if (stroke instanceof BasicStroke)
- {
- PathIterator flatten = s.getPathIterator(null, 1.0);
- GeneralPath p = new GeneralPath();
- p.append(flatten, false);
- s = p;
- }
- fill(stroke.createStrokedShape(s));
- return;
+ // Cairo doesn't support stroking with alpha, so we create the stroked
+ // shape and fill with alpha instead
+ fill(stroke.createStrokedShape(s));
+ return;
}
- cairoNewPath(nativePointer);
-
- if (s instanceof Rectangle2D)
- {
- Rectangle2D r = (Rectangle2D) s;
- cairoRectangle(nativePointer, shifted(r.getX(), shiftDrawCalls),
- shifted(r.getY(), shiftDrawCalls), r.getWidth(),
- r.getHeight());
- }
- else
- walkPath(s.getPathIterator(null), shiftDrawCalls);
+ createPath(s);
cairoStroke(nativePointer);
}
public void fill(Shape s)
{
+ createPath(s);
+
+ double alpha = 1.0;
+ if (comp instanceof AlphaComposite)
+ alpha = ((AlphaComposite) comp).getAlpha();
+ cairoFill(nativePointer, alpha);
+ }
+
+ private void createPath(Shape s)
+ {
cairoNewPath(nativePointer);
+
+ // Optimize rectangles, since there is a direct Cairo function
if (s instanceof Rectangle2D)
{
- Rectangle2D r = (Rectangle2D) s;
- cairoRectangle(nativePointer, r.getX(), r.getY(), r.getWidth(),
+ Rectangle2D r = (Rectangle2D) s;
+ cairoRectangle(nativePointer, shifted(r.getX(), shiftDrawCalls),
+ shifted(r.getY(), shiftDrawCalls), r.getWidth(),
r.getHeight());
}
- else
- walkPath(s.getPathIterator(null), false);
- double alpha = 1.0;
- if (comp instanceof AlphaComposite)
- alpha = ((AlphaComposite) comp).getAlpha();
- cairoFill(nativePointer, alpha);
+ // We can optimize ellipses too; however we don't bother optimizing arcs:
+ // the iterator is fast enough (an ellipse requires 5 steps using the
+ // iterator, while most arcs are only 2-3)
+ else if (s instanceof Ellipse2D)
+ {
+ Ellipse2D e = (Ellipse2D) s;
+
+ double radius = Math.min(e.getHeight(), e.getWidth()) / 2;
+
+ // Cairo only draws circular shapes, but we can use a stretch to make
+ // them into ellipses
+ double xscale = 1, yscale = 1;
+ if (e.getHeight() != e.getWidth())
+ {
+ cairoSave(nativePointer);
+
+ if (e.getHeight() < e.getWidth())
+ xscale = e.getWidth() / (radius * 2);
+ else
+ yscale = e.getHeight() / (radius * 2);
+
+ if (xscale != 1 || yscale != 1)
+ cairoScale(nativePointer, xscale, yscale);
+ }
+
+ cairoArc(nativePointer,
+ shifted(e.getCenterX() / xscale, shiftDrawCalls),
+ shifted(e.getCenterY() / yscale, shiftDrawCalls), radius, 0,
+ Math.PI * 2);
+
+ if (xscale != 1 || yscale != 1)
+ cairoRestore(nativePointer);
+ }
+
+ // All other shapes are broken down and drawn in steps using the
+ // PathIterator
+ else
+ walkPath(s.getPathIterator(null), shiftDrawCalls);
}
/**
@@ -985,9 +1029,13 @@ public abstract class CairoGraphics2D extends Graphics2D
public void drawLine(int x1, int y1, int x2, int y2)
{
- cairoDrawLine(nativePointer, shifted(x1, shiftDrawCalls),
- shifted(y1, shiftDrawCalls), shifted(x2, shiftDrawCalls),
- shifted(y2, shiftDrawCalls));
+ // The coordinates being pairwise identical means one wants
+ // to draw a single pixel. This is emulated by drawing
+ // a one pixel sized rectangle.
+ if (x1 == x2 && y1 == y2)
+ cairoFillRect(nativePointer, x1, y1, 1, 1);
+ else
+ cairoDrawLine(nativePointer, x1 + 0.5, y1 + 0.5, x2 + 0.5, y2 + 0.5);
}
public void drawRect(int x, int y, int width, int height)
@@ -1185,6 +1233,9 @@ public abstract class CairoGraphics2D extends Graphics2D
if (img == null)
return false;
+ if (xform == null)
+ xform = new AffineTransform();
+
// In this case, xform is an AffineTransform that transforms bounding
// box of the specified image from image space to user space. However
// when we pass this transform to cairo, cairo will use this transform
@@ -1218,7 +1269,7 @@ public abstract class CairoGraphics2D extends Graphics2D
}
BufferedImage b = (BufferedImage) img;
- DataBuffer db;
+ Raster raster;
double[] i2u = new double[6];
int width = b.getWidth();
int height = b.getHeight();
@@ -1227,9 +1278,9 @@ public abstract class CairoGraphics2D extends Graphics2D
// use the cached CairoSurface that BIG is drawing onto
if( BufferedImageGraphics.bufferedImages.get( b ) != null )
- db = (DataBuffer)BufferedImageGraphics.bufferedImages.get( b );
+ raster = (Raster)BufferedImageGraphics.bufferedImages.get( b );
else
- db = b.getRaster().getDataBuffer();
+ raster = b.getRaster();
invertedXform.getMatrix(i2u);
@@ -1237,9 +1288,9 @@ public abstract class CairoGraphics2D extends Graphics2D
if (comp instanceof AlphaComposite)
alpha = ((AlphaComposite) comp).getAlpha();
- if(db instanceof CairoSurface)
+ if(raster instanceof CairoSurface)
{
- ((CairoSurface)db).drawSurface(nativePointer, i2u, alpha);
+ ((CairoSurface)raster).drawSurface(nativePointer, i2u, alpha);
updateColor();
return true;
}
@@ -1283,7 +1334,9 @@ public abstract class CairoGraphics2D extends Graphics2D
public void drawImage(BufferedImage image, BufferedImageOp op, int x, int y)
{
- Image filtered = op.filter(image, null);
+ Image filtered = image;
+ if (op != null)
+ filtered = op.filter(image, null);
drawImage(filtered, new AffineTransform(1f, 0f, 0f, 1f, x, y), null, null);
}
@@ -1405,8 +1458,11 @@ public abstract class CairoGraphics2D extends Graphics2D
float[] positions = gv.getGlyphPositions (0, n, null);
setFont (gv.getFont ());
- cairoDrawGlyphVector(nativePointer, (GdkFontPeer)getFont().getPeer(),
- x, y, n, codes, positions);
+ synchronized( this.font )
+ {
+ cairoDrawGlyphVector(nativePointer, (GdkFontPeer)getFont().getPeer(),
+ x, y, n, codes, positions);
+ }
}
else
{
diff --git a/gnu/java/awt/peer/gtk/CairoSurface.java b/gnu/java/awt/peer/gtk/CairoSurface.java
index b4d08c6ad..3bf9a9ccf 100644
--- a/gnu/java/awt/peer/gtk/CairoSurface.java
+++ b/gnu/java/awt/peer/gtk/CairoSurface.java
@@ -38,34 +38,24 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-import java.awt.Graphics;
-import java.awt.Color;
-import java.awt.Image;
import java.awt.Point;
import java.awt.Graphics2D;
-import java.awt.GraphicsConfiguration;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
-import java.io.File;
-import java.io.IOException;
+import java.awt.image.SinglePixelPackedSampleModel;
import java.nio.ByteOrder;
import java.util.Hashtable;
-import java.util.Vector;
-import java.io.ByteArrayOutputStream;
-import java.io.BufferedInputStream;
-import java.net.URL;
-import gnu.classpath.Pointer;
/**
* CairoSurface - wraps a Cairo surface.
*
* @author Sven de Marothy
*/
-public class CairoSurface extends DataBuffer
+public class CairoSurface extends WritableRaster
{
int width = -1, height = -1;
@@ -79,11 +69,10 @@ public class CairoSurface extends DataBuffer
*/
long bufferPointer;
-
- static ColorModel nativeModel = new DirectColorModel(32,
- 0x000000FF,
- 0x0000FF00,
+ static ColorModel nativeModel = new DirectColorModel(32,
0x00FF0000,
+ 0x0000FF00,
+ 0x000000FF,
0xFF000000);
/**
@@ -149,18 +138,22 @@ public class CairoSurface extends DataBuffer
*/
public CairoSurface(int width, int height)
{
- super(DataBuffer.TYPE_INT, width * height);
+ super( new SinglePixelPackedSampleModel
+ (DataBuffer.TYPE_INT, width, height,
+ new int[]{ 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }),
+ null, new Point(0, 0) );
if(width <= 0 || height <= 0)
throw new IllegalArgumentException("Image must be at least 1x1 pixels.");
-
+
this.width = width;
this.height = height;
-
create(width, height, width);
if(surfacePointer == 0 || bufferPointer == 0)
throw new Error("Could not allocate bitmap.");
+
+ dataBuffer = new CairoDataBuffer();
}
/**
@@ -169,59 +162,42 @@ public class CairoSurface extends DataBuffer
*/
CairoSurface(GtkImage image)
{
- super(DataBuffer.TYPE_INT, image.width * image.height);
-
- if(image.width <= 0 || image.height <= 0)
- throw new IllegalArgumentException("Image must be at least 1x1 pixels.");
-
- width = image.width;
- height = image.height;
-
- create(width, height, width);
-
- if(surfacePointer == 0 || bufferPointer == 0)
- throw new Error("Could not allocate bitmap.");
+ this(image.width, image.height);
// Copy the pixel data from the GtkImage.
int[] data = image.getPixels();
// Swap ordering from GdkPixbuf to Cairo
- for(int i = 0; i < data.length; i++ )
+ if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
{
- if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
+ for (int i = 0; i < data.length; i++ )
{
// On a big endian system we get a RRGGBBAA data array.
- int alpha = (data[i] & 0xFF);
+ int alpha = data[i] & 0xFF;
if( alpha == 0 ) // I do not know why we need this, but it works.
data[i] = 0;
else
{
- int r = (((data[i] & 0xFF000000) >> 24));
- int g = (((data[i] & 0x00FF0000) >> 16));
- int b = (((data[i] & 0x0000FF00) >> 8));
// Cairo needs a ARGB32 native array.
- data[i] = (( alpha << 24 ) & 0xFF000000)
- | (( r << 16 ) & 0x00FF0000)
- | (( g << 8 ) & 0x0000FF00)
- | ( b & 0x000000FF);
+ data[i] = (data[i] >>> 8) | (alpha << 24);
}
}
- else
+ }
+ else
+ {
+ for (int i = 0; i < data.length; i++ )
{
// On a little endian system we get a AABBGGRR data array.
- int alpha = (data[i] & 0xFF000000) >> 24;
+ int alpha = data[i] & 0xFF000000;
if( alpha == 0 ) // I do not know why we need this, but it works.
data[i] = 0;
else
{
- int b = (((data[i] & 0x00FF0000) >> 16));
- int g = (((data[i] & 0x0000FF00) >> 8));
- int r = ((data[i] & 0x000000FF));
+ int b = (data[i] & 0xFF0000) >> 16;
+ int g = (data[i] & 0xFF00);
+ int r = (data[i] & 0xFF) << 16;
// Cairo needs a ARGB32 native array.
- data[i] = (( alpha << 24 ) & 0xFF000000)
- | (( r << 16 ) & 0x00FF0000)
- | (( g << 8 ) & 0x0000FF00)
- | ( b & 0x000000FF);
+ data[i] = alpha | r | g | b;
}
}
}
@@ -277,32 +253,35 @@ public class CairoSurface extends DataBuffer
*/
public static BufferedImage getBufferedImage(CairoSurface surface)
{
- WritableRaster raster = Raster.createPackedRaster
- (surface, surface.width, surface.height, surface.width,
- new int[]{ 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 },
- new Point(0,0));
-
- return new BufferedImage(nativeModel, raster, true, new Hashtable());
+ return new BufferedImage(nativeModel, surface, true, new Hashtable());
}
- /**
- * DataBank.getElem implementation
- */
- public int getElem(int bank, int i)
+ private class CairoDataBuffer extends DataBuffer
{
- if(bank != 0 || i < 0 || i >= width*height)
- throw new IndexOutOfBoundsException(i+" size: "+width*height);
- return nativeGetElem(bufferPointer, i);
- }
+ public CairoDataBuffer()
+ {
+ super(DataBuffer.TYPE_INT, width * height);
+ }
+
+ /**
+ * DataBuffer.getElem implementation
+ */
+ public int getElem(int bank, int i)
+ {
+ if(bank != 0 || i < 0 || i >= width * height)
+ throw new IndexOutOfBoundsException(i+" size: "+width * height);
+ return nativeGetElem(bufferPointer, i);
+ }
- /**
- * DataBank.setElem implementation
- */
- public void setElem(int bank, int i, int val)
- {
- if(bank != 0 || i < 0 || i >= width*height)
- throw new IndexOutOfBoundsException(i+" size: "+width*height);
- nativeSetElem(bufferPointer, i, val);
+ /**
+ * DataBuffer.setElem implementation
+ */
+ public void setElem(int bank, int i, int val)
+ {
+ if(bank != 0 || i < 0 || i >= width*height)
+ throw new IndexOutOfBoundsException(i+" size: "+width * height);
+ nativeSetElem(bufferPointer, i, val);
+ }
}
/**
diff --git a/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java b/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
index 91f0b4981..7bd136c38 100644
--- a/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
+++ b/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
@@ -39,14 +39,9 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
import java.awt.Graphics;
-import java.awt.Color;
import java.awt.GraphicsEnvironment;
-import java.awt.Image;
-import java.awt.Point;
-import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.geom.Rectangle2D;
-import java.awt.image.*;
/**
* Implementation of Graphics2D on a Cairo surface.
diff --git a/gnu/java/awt/peer/gtk/ComponentGraphics.java b/gnu/java/awt/peer/gtk/ComponentGraphics.java
index cb8350265..d9d173118 100644
--- a/gnu/java/awt/peer/gtk/ComponentGraphics.java
+++ b/gnu/java/awt/peer/gtk/ComponentGraphics.java
@@ -53,6 +53,7 @@ import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.RenderedImage;
+import gnu.classpath.Pointer;
/**
* ComponentGraphics - context for drawing directly to a component,
@@ -62,38 +63,14 @@ import java.awt.image.RenderedImage;
*/
public class ComponentGraphics extends CairoGraphics2D
{
+ private static final boolean hasXRenderExtension = hasXRender();
+
private GtkComponentPeer component;
protected long cairo_t;
private static ThreadLocal hasLock = new ThreadLocal();
private static Integer ONE = Integer.valueOf(1);
- private void lock()
- {
- Integer i = (Integer) hasLock.get();
- if (i == null)
- {
- start_gdk_drawing();
- hasLock.set(ONE);
- }
- else
- hasLock.set(Integer.valueOf(i.intValue() + 1));
- }
-
- private void unlock()
- {
- Integer i = (Integer) hasLock.get();
- if (i == null)
- throw new IllegalStateException();
- if (i == ONE)
- {
- hasLock.set(null);
- end_gdk_drawing();
- }
- else
- hasLock.set(Integer.valueOf(i.intValue() - 1));
- }
-
ComponentGraphics()
{
}
@@ -125,6 +102,32 @@ public class ComponentGraphics extends CairoGraphics2D
*/
private native long initState(GtkComponentPeer component);
+ private void lock()
+ {
+ Integer i = (Integer) hasLock.get();
+ if (i == null)
+ {
+ start_gdk_drawing();
+ hasLock.set(ONE);
+ }
+ else
+ hasLock.set(Integer.valueOf(i.intValue() + 1));
+ }
+
+ private void unlock()
+ {
+ Integer i = (Integer) hasLock.get();
+ if (i == null)
+ throw new IllegalStateException();
+ if (i == ONE)
+ {
+ hasLock.set(null);
+ end_gdk_drawing();
+ }
+ else
+ hasLock.set(Integer.valueOf(i.intValue() - 1));
+ }
+
/**
* Destroys the component surface and calls dispose on the cairo
* graphics2d to destroy any super class resources.
@@ -160,6 +163,11 @@ public class ComponentGraphics extends CairoGraphics2D
*/
public static native boolean hasXRender();
+ /**
+ * This is a utility method (used by GtkComponentPeer) for grabbing the
+ * image of a component.
+ */
+ private static native Pointer nativeGrab(GtkComponentPeer component);
private native void copyAreaNative(GtkComponentPeer component, int x, int y,
int width, int height, int dx, int dy);
@@ -170,12 +178,20 @@ public class ComponentGraphics extends CairoGraphics2D
int cw, int ch);
/**
+ * Not really related (moveme?). Utility method used by GtkComponent.
+ */
+ public static GtkImage grab( GtkComponentPeer component )
+ {
+ return new GtkImage( nativeGrab( component ) );
+ }
+
+ /**
* Returns a Graphics2D object for a component, either an instance of this
* class (if xrender is supported), or a context which copies.
*/
public static Graphics2D getComponentGraphics(GtkComponentPeer component)
{
- if( hasXRender() )
+ if( hasXRenderExtension )
return new ComponentGraphics(component);
Rectangle r = component.awtComponent.getBounds();
@@ -402,5 +418,18 @@ public class ComponentGraphics extends CairoGraphics2D
}
}
+ public void setClip(Shape s)
+ {
+ lock();
+ try
+ {
+ super.setClip(s);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
}
diff --git a/gnu/java/awt/peer/gtk/ComponentGraphicsCopy.java b/gnu/java/awt/peer/gtk/ComponentGraphicsCopy.java
index 286fbeac0..2216d459a 100644
--- a/gnu/java/awt/peer/gtk/ComponentGraphicsCopy.java
+++ b/gnu/java/awt/peer/gtk/ComponentGraphicsCopy.java
@@ -39,17 +39,11 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
import java.awt.Color;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.GraphicsConfiguration;
import java.awt.Image;
-import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
-import java.awt.image.BufferedImage;
-import java.awt.image.DataBuffer;
import java.awt.image.RenderedImage;
import java.awt.image.ImageObserver;
diff --git a/gnu/java/awt/peer/gtk/GdkFontPeer.java b/gnu/java/awt/peer/gtk/GdkFontPeer.java
index f5ed8a710..11635c354 100644
--- a/gnu/java/awt/peer/gtk/GdkFontPeer.java
+++ b/gnu/java/awt/peer/gtk/GdkFontPeer.java
@@ -38,7 +38,6 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-import gnu.classpath.Configuration;
import gnu.java.awt.peer.ClasspathFontPeer;
import gnu.java.awt.font.opentype.NameDecoder;
@@ -50,9 +49,7 @@ import java.awt.font.GlyphVector;
import java.awt.font.GlyphMetrics;
import java.awt.font.LineMetrics;
import java.awt.geom.Rectangle2D;
-import java.awt.geom.Point2D;
import java.text.CharacterIterator;
-import java.text.StringCharacterIterator;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
diff --git a/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java b/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
index 035819d1c..db725b697 100644
--- a/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
+++ b/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
@@ -44,7 +44,7 @@ import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.image.BufferedImage;
-import java.awt.image.DataBuffer;
+import java.awt.image.Raster;
import java.util.Locale;
public class GdkGraphicsEnvironment extends GraphicsEnvironment
@@ -103,9 +103,9 @@ public class GdkGraphicsEnvironment extends GraphicsEnvironment
public Graphics2D createGraphics (BufferedImage image)
{
- DataBuffer db = image.getRaster().getDataBuffer();
- if(db instanceof CairoSurface)
- return ((CairoSurface)db).getGraphics();
+ Raster raster = image.getRaster();
+ if(raster instanceof CairoSurface)
+ return ((CairoSurface)raster).getGraphics();
return new BufferedImageGraphics( image );
}
@@ -134,5 +134,9 @@ public class GdkGraphicsEnvironment extends GraphicsEnvironment
{
throw new java.lang.UnsupportedOperationException ();
}
-
+
+ /**
+ * Used by GtkMouseInfoPeer.
+ */
+ native int[] getMouseCoordinates();
}
diff --git a/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java b/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
index cd047f267..6d0a52b91 100644
--- a/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
+++ b/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
@@ -38,13 +38,10 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-import gnu.classpath.Configuration;
-
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.ImageConsumer;
-import java.awt.image.ImageProducer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.io.DataInput;
diff --git a/gnu/java/awt/peer/gtk/GtkButtonPeer.java b/gnu/java/awt/peer/gtk/GtkButtonPeer.java
index 63d9cd487..f18db7af9 100644
--- a/gnu/java/awt/peer/gtk/GtkButtonPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkButtonPeer.java
@@ -38,13 +38,8 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-import java.awt.AWTEvent;
import java.awt.Button;
-import java.awt.Component;
-import java.awt.Point;
import java.awt.event.ActionEvent;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
import java.awt.peer.ButtonPeer;
// A composite widget. GtkButtons have transparent backgrounds. An
diff --git a/gnu/java/awt/peer/gtk/GtkCanvasPeer.java b/gnu/java/awt/peer/gtk/GtkCanvasPeer.java
index edfc9ceee..30c39dede 100644
--- a/gnu/java/awt/peer/gtk/GtkCanvasPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkCanvasPeer.java
@@ -53,8 +53,8 @@ public class GtkCanvasPeer extends GtkComponentPeer implements CanvasPeer
// Preferred size for a drawing widget is always what the user
// requested.
- public Dimension getPreferredSize ()
+ public Dimension preferredSize()
{
- return awtComponent.getSize ();
+ return awtComponent.getSize();
}
}
diff --git a/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java b/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
index 1c5400c27..90d16c572 100644
--- a/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
@@ -246,6 +246,9 @@ public class GtkCheckboxPeer extends GtkComponentPeer
public void dispose ()
{
+ groupMap.clear();
+ current_group = null;
+ currentState = false;
super.dispose ();
}
}
diff --git a/gnu/java/awt/peer/gtk/GtkChoicePeer.java b/gnu/java/awt/peer/gtk/GtkChoicePeer.java
index ed7dc74d2..d866cefd3 100644
--- a/gnu/java/awt/peer/gtk/GtkChoicePeer.java
+++ b/gnu/java/awt/peer/gtk/GtkChoicePeer.java
@@ -39,12 +39,15 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
import java.awt.Choice;
+import java.awt.AWTEvent;
import java.awt.event.ItemEvent;
import java.awt.peer.ChoicePeer;
public class GtkChoicePeer extends GtkComponentPeer
implements ChoicePeer
{
+ private int selected;
+
public GtkChoicePeer (Choice c)
{
super (c);
@@ -52,75 +55,53 @@ public class GtkChoicePeer extends GtkComponentPeer
int count = c.getItemCount ();
if (count > 0)
{
- String items[] = new String[count];
for (int i = 0; i < count; i++)
- items[i] = c.getItem (i);
-
- append (items);
- }
+ add( c.getItem(i), i );
- int selected = c.getSelectedIndex();
- if (selected >= 0)
- select(selected);
+ selected = c.getSelectedIndex();
+ if( selected >= 0 )
+ select( selected );
+ }
+ else
+ selected = -1;
}
native void create ();
- native void append (String items[]);
native int nativeGetSelected ();
- native void nativeAdd (String item, int index);
- native void nativeRemove (int index);
- native void nativeRemoveAll ();
native void connectSignals ();
native void selectNative (int position);
+
native void selectNativeUnlocked (int position);
+ public native void add (String item, int index);
+
+ native void nativeRemove(int index);
+
+ native void nativeRemoveAll();
+
public void select (int position)
{
- if (Thread.currentThread() == GtkToolkit.mainThread)
+ if (Thread.currentThread() == GtkMainThread.mainThread)
selectNativeUnlocked (position);
else
selectNative (position);
}
- public void add (String item, int index)
+ public void remove( int index )
{
- int before = nativeGetSelected();
-
- nativeAdd (item, index);
-
- /* Generate an ItemEvent if we added the first one or
- if we inserted at or before the currently selected item. */
- if ((before < 0) || (before >= index))
- {
- // Must set our state before notifying listeners
- ((Choice) awtComponent).select (((Choice) awtComponent).getItem (0));
- postItemEvent (((Choice) awtComponent).getItem (0), ItemEvent.SELECTED);
- }
+ // Ensure the triggering of an event when removing item zero if zero is the
+ // selected item, even though the selected index doesn't change.
+ if( index == 0 && selected == 0 )
+ selected = -1;
+ nativeRemove( index );
}
- public void remove (int index)
- {
- int before = nativeGetSelected();
- int after;
-
- nativeRemove (index);
- after = nativeGetSelected();
-
- /* Generate an ItemEvent if we are removing the currently selected item
- and there are at least one item left. */
- if ((before == index) && (after >= 0))
- {
- // Must set our state before notifying listeners
- ((Choice) awtComponent).select (((Choice) awtComponent).getItem (0));
- postItemEvent (((Choice) awtComponent).getItem (0), ItemEvent.SELECTED);
- }
- }
-
- public void removeAll ()
+ public void removeAll()
{
+ selected = -1; // we do not want to trigger a select event here.
nativeRemoveAll();
}
@@ -129,8 +110,34 @@ public class GtkChoicePeer extends GtkComponentPeer
add (item, position);
}
- protected void postChoiceItemEvent (String label, int stateChange)
+ /**
+ * Callback from the native side on an item-select event,
+ * which posts an event. The event is only posted if it represents an actual
+ * change. Selected is set to the peer's state initially, so that the
+ * first call to select(int) from the constructor will not trigger an event.
+ * (it should not)
+ */
+ protected void postChoiceItemEvent ( int index )
+ {
+ if( selected != index )
+ {
+ selected = index;
+ postItemEvent (((Choice) awtComponent).getItem( selected ),
+ ItemEvent.SELECTED);
+ }
+ }
+
+ /**
+ * Catches the event and calls Choice.select() if the component state
+ * needs updating.
+ */
+ public void handleEvent (AWTEvent event)
{
- postItemEvent (label, stateChange);
+ super.handleEvent( event );
+ if( event instanceof ItemEvent )
+ if( ((ItemEvent)event).getItemSelectable() == awtComponent &&
+ ((ItemEvent)event).getStateChange() == ItemEvent.SELECTED )
+ ((Choice)awtComponent).select( selected );
}
}
+
diff --git a/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java b/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java
index fdc7d50c5..61df796dc 100644
--- a/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java
+++ b/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java
@@ -1,5 +1,5 @@
/* GtkClipboardNotifier.java -- Helper for announcing GtkSelection changes.
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,8 +38,6 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-import java.awt.datatransfer.*;
-import java.util.*;
class GtkClipboardNotifier extends Thread
{
diff --git a/gnu/java/awt/peer/gtk/GtkComponentPeer.java b/gnu/java/awt/peer/gtk/GtkComponentPeer.java
index dcbac1259..f96033e56 100644
--- a/gnu/java/awt/peer/gtk/GtkComponentPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkComponentPeer.java
@@ -57,6 +57,7 @@ import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Insets;
import java.awt.ItemSelectable;
+import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
@@ -68,13 +69,13 @@ import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.PaintEvent;
import java.awt.event.TextEvent;
-import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.VolatileImage;
import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
+import java.awt.peer.LightweightPeer;
import java.awt.peer.WindowPeer;
import java.util.Timer;
import java.util.TimerTask;
@@ -111,6 +112,9 @@ public class GtkComponentPeer extends GtkGenericPeer
native void gtkWidgetRequestFocus ();
native void gtkWidgetDispatchKeyEvent (int id, long when, int mods,
int keyCode, int keyLocation);
+ native boolean gtkWidgetHasFocus();
+ native boolean gtkWidgetCanFocus();
+
native void realize();
native void setNativeEventMask ();
@@ -367,7 +371,7 @@ public class GtkComponentPeer extends GtkGenericPeer
public void print (Graphics g)
{
- throw new RuntimeException ();
+ g.drawImage( ComponentGraphics.grab( this ), 0, 0, null );
}
public void repaint (long tm, int x, int y, int width, int height)
@@ -416,8 +420,7 @@ public class GtkComponentPeer extends GtkGenericPeer
public void requestFocus ()
{
- gtkWidgetRequestFocus();
- postFocusEvent(FocusEvent.FOCUS_GAINED, false);
+ assert false: "Call new requestFocus() method instead";
}
public void reshape (int x, int y, int width, int height)
@@ -511,7 +514,7 @@ public class GtkComponentPeer extends GtkGenericPeer
y = 0;
}
- if (Thread.currentThread() == GtkToolkit.mainThread)
+ if (Thread.currentThread() == GtkMainThread.mainThread)
gtkWidgetSetCursorUnlocked(cursor.getType(), image, x, y);
else
gtkWidgetSetCursor(cursor.getType(), image, x, y);
@@ -559,7 +562,7 @@ public class GtkComponentPeer extends GtkGenericPeer
b = (bounds.width > 0) && (bounds.height > 0);
}
- if (Thread.currentThread() == GtkToolkit.mainThread)
+ if (Thread.currentThread() == GtkMainThread.mainThread)
setVisibleNativeUnlocked (b);
else
setVisibleNative (b);
@@ -630,6 +633,12 @@ public class GtkComponentPeer extends GtkGenericPeer
q.postEvent(keyEvent);
}
+ /**
+ * Referenced from native code.
+ *
+ * @param id
+ * @param temporary
+ */
protected void postFocusEvent (int id, boolean temporary)
{
q().postEvent (new FocusEvent (awtComponent, id, temporary));
@@ -665,10 +674,72 @@ public class GtkComponentPeer extends GtkGenericPeer
return false;
}
- public boolean requestFocus (Component source, boolean b1,
- boolean b2, long x)
+ public boolean requestFocus (Component request, boolean temporary,
+ boolean allowWindowFocus, long time)
{
- return false;
+ assert request == awtComponent || isLightweightDescendant(request);
+ boolean retval = false;
+ if (gtkWidgetHasFocus())
+ {
+ KeyboardFocusManager kfm =
+ KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ Component currentFocus = kfm.getFocusOwner();
+ if (currentFocus == request)
+ // Nothing to do in this trivial case.
+ retval = true;
+ else
+ {
+ // Requested component is a lightweight descendant of this one
+ // or the actual heavyweight.
+ // Since this (native) component is already focused, we simply
+ // change the actual focus and be done.
+ postFocusEvent(FocusEvent.FOCUS_GAINED, temporary);
+ retval = true;
+ }
+ }
+ else
+ {
+ if (gtkWidgetCanFocus())
+ {
+ if (allowWindowFocus)
+ {
+ Window window = getWindowFor(request);
+ GtkWindowPeer wPeer = (GtkWindowPeer) window.getPeer();
+ if (! wPeer.gtkWindowHasFocus())
+ wPeer.requestWindowFocus();
+ }
+ // Store requested focus component so that the corresponding
+ // event is dispatched correctly.
+ gtkWidgetRequestFocus();
+ retval = true;
+ }
+ }
+ return retval;
+ }
+
+ private Window getWindowFor(Component c)
+ {
+ Component comp = c;
+ while (! (comp instanceof Window))
+ comp = comp.getParent();
+ return (Window) comp;
+ }
+
+ /**
+ * Returns <code>true</code> if the component is a direct (== no intermediate
+ * heavyweights) lightweight descendant of this peer's component.
+ *
+ * @param c the component to check
+ *
+ * @return <code>true</code> if the component is a direct (== no intermediate
+ * heavyweights) lightweight descendant of this peer's component
+ */
+ protected boolean isLightweightDescendant(Component c)
+ {
+ Component comp = c;
+ while (comp.getPeer() instanceof LightweightPeer)
+ comp = comp.getParent();
+ return comp == awtComponent;
}
public boolean isObscured ()
diff --git a/gnu/java/awt/peer/gtk/GtkContainerPeer.java b/gnu/java/awt/peer/gtk/GtkContainerPeer.java
index 06076e77f..541de3d82 100644
--- a/gnu/java/awt/peer/gtk/GtkContainerPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkContainerPeer.java
@@ -42,10 +42,7 @@ import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
-import java.awt.Graphics;
import java.awt.Insets;
-import java.awt.Window;
-import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
public class GtkContainerPeer extends GtkComponentPeer
diff --git a/gnu/java/awt/peer/gtk/GtkDialogPeer.java b/gnu/java/awt/peer/gtk/GtkDialogPeer.java
index 3254f566d..13906544d 100644
--- a/gnu/java/awt/peer/gtk/GtkDialogPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkDialogPeer.java
@@ -1,5 +1,5 @@
/* GtkDialogPeer.java -- Implements DialogPeer with GTK
- Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2002, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,9 +39,6 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
import java.awt.Dialog;
-import java.awt.Graphics;
-import java.awt.Rectangle;
-import java.awt.event.PaintEvent;
import java.awt.peer.DialogPeer;
public class GtkDialogPeer extends GtkWindowPeer
diff --git a/gnu/java/awt/peer/gtk/GtkFramePeer.java b/gnu/java/awt/peer/gtk/GtkFramePeer.java
index 6ec0b7298..bb6f8b3bb 100644
--- a/gnu/java/awt/peer/gtk/GtkFramePeer.java
+++ b/gnu/java/awt/peer/gtk/GtkFramePeer.java
@@ -39,11 +39,9 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
import java.awt.Frame;
-import java.awt.Graphics;
import java.awt.Image;
import java.awt.MenuBar;
import java.awt.Rectangle;
-import java.awt.event.PaintEvent;
import java.awt.peer.FramePeer;
import java.awt.peer.MenuBarPeer;
@@ -218,11 +216,7 @@ public class GtkFramePeer extends GtkWindowPeer
// TODO Auto-generated method stub
}
- public void updateAlwaysOnTop()
- {
- // TODO Auto-generated method stub
-
- }
+
public boolean requestWindowFocus()
{
// TODO Auto-generated method stub
diff --git a/gnu/java/awt/peer/gtk/GtkImage.java b/gnu/java/awt/peer/gtk/GtkImage.java
index ef96518a1..0fd98bbd7 100644
--- a/gnu/java/awt/peer/gtk/GtkImage.java
+++ b/gnu/java/awt/peer/gtk/GtkImage.java
@@ -39,12 +39,10 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
import java.awt.Graphics;
-import java.awt.Color;
import java.awt.Image;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.MemoryImageSource;
-import java.awt.image.ImageConsumer;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.io.File;
diff --git a/gnu/java/awt/peer/gtk/GtkImageConsumer.java b/gnu/java/awt/peer/gtk/GtkImageConsumer.java
index 299f01dca..f1a74b8cc 100644
--- a/gnu/java/awt/peer/gtk/GtkImageConsumer.java
+++ b/gnu/java/awt/peer/gtk/GtkImageConsumer.java
@@ -1,5 +1,5 @@
/* GtkImageConsumer.java
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,16 +38,11 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-import java.awt.Graphics;
-import java.awt.Image;
import java.awt.image.ColorModel;
-import java.awt.image.DirectColorModel;
import java.awt.image.ImageConsumer;
-import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.MemoryImageSource;
import java.util.Hashtable;
-import java.util.Vector;
/**
* Helper class to GtkImage. Sits and gathers pixels for a GtkImage and then
diff --git a/gnu/java/awt/peer/gtk/GtkMainThread.java b/gnu/java/awt/peer/gtk/GtkMainThread.java
new file mode 100644
index 000000000..19d3f1d0b
--- /dev/null
+++ b/gnu/java/awt/peer/gtk/GtkMainThread.java
@@ -0,0 +1,97 @@
+/* GtkMainThread.java -- Wrapper for the GTK main thread, and some utilities.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+public class GtkMainThread extends Thread
+{
+ /** Count of the number of open windows */
+ private static int numberOfWindows = 0;
+
+ /** Lock for the above */
+ private static Object nWindowsLock = new Object();
+
+ /** The main thread instance (singleton) */
+ public static GtkMainThread mainThread;
+
+ /** Constructs a main thread */
+ private GtkMainThread()
+ {
+ super("GTK main thread");
+ }
+
+ public void run ()
+ {
+ GtkToolkit.gtkMain ();
+ }
+
+ private static void startMainThread()
+ {
+ if( mainThread == null )
+ {
+ mainThread = new GtkMainThread();
+ mainThread.start();
+ }
+ }
+
+ private static void endMainThread()
+ {
+ if( mainThread != null )
+ GtkToolkit.gtkQuit();
+ }
+
+ public static void createWindow()
+ {
+ synchronized( nWindowsLock )
+ {
+ if( numberOfWindows == 0 )
+ startMainThread();
+ numberOfWindows++;
+ }
+ }
+
+ public static void destroyWindow()
+ {
+ synchronized( nWindowsLock )
+ {
+ numberOfWindows--;
+ if( numberOfWindows == 0 )
+ endMainThread();
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java b/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java
index d203b437f..898f224f5 100644
--- a/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java
@@ -38,12 +38,9 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-import java.awt.Font;
import java.awt.Menu;
import java.awt.MenuBar;
-import java.awt.MenuComponent;
import java.awt.peer.MenuBarPeer;
-import java.awt.peer.MenuPeer;
public class GtkMenuBarPeer extends GtkMenuComponentPeer
implements MenuBarPeer
diff --git a/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java b/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java
index 251bab233..ea523e953 100644
--- a/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java
@@ -38,13 +38,8 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-import java.awt.Font;
-import java.awt.Menu;
-import java.awt.MenuBar;
-import java.awt.MenuComponent;
import java.awt.MenuItem;
import java.awt.peer.MenuItemPeer;
-import java.awt.peer.MenuPeer;
public class GtkMenuItemPeer extends GtkMenuComponentPeer
implements MenuItemPeer
diff --git a/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java b/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java
new file mode 100644
index 000000000..02bf84d4e
--- /dev/null
+++ b/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java
@@ -0,0 +1,76 @@
+/* GtkToolkit.java -- Implements an AWT Toolkit using GTK for peers
+ Copyright (C) 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Point;
+import java.awt.GraphicsDevice;
+import java.awt.Window;
+import java.awt.peer.MouseInfoPeer;
+
+/**
+ * The MouseInfoPeer is so small, I'm including it here.
+ */
+public class GtkMouseInfoPeer implements MouseInfoPeer
+{
+ private static GdkGraphicsEnvironment gde = new GdkGraphicsEnvironment();
+
+ public int fillPointWithCoords(Point p)
+ {
+ int[] coords = gde.getMouseCoordinates();
+ p.x = coords[1];
+ p.y = coords[2];
+ return coords[0];
+ }
+
+ public boolean isWindowUnderMouse(Window w)
+ {
+ int[] coords = gde.getMouseCoordinates();
+ GraphicsDevice[] gds = gde.getScreenDevices();
+
+ // Check if the screen of the Window and the cursor match
+ if( gds[ coords[0] ] != w.getGraphicsConfiguration().getDevice() )
+ return false;
+
+ // Return the bounds-check.
+ Point p = w.getLocationOnScreen();
+ return (coords[1] >= p.x && coords[1] < p.x + w.getWidth() &&
+ coords[2] >= p.y && coords[2] < p.y + w.getHeight() );
+ }
+}
+
diff --git a/gnu/java/awt/peer/gtk/GtkPanelPeer.java b/gnu/java/awt/peer/gtk/GtkPanelPeer.java
index 51fe2bc8e..e0053f763 100644
--- a/gnu/java/awt/peer/gtk/GtkPanelPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkPanelPeer.java
@@ -1,5 +1,5 @@
/* GtkPanelPeer.java -- Implements PanelPeer with GTK
- Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,7 +41,6 @@ package gnu.java.awt.peer.gtk;
import java.awt.AWTEvent;
import java.awt.Panel;
import java.awt.event.MouseEvent;
-import java.awt.event.PaintEvent;
import java.awt.peer.PanelPeer;
public class GtkPanelPeer extends GtkContainerPeer
diff --git a/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java b/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java
index 525a910bc..4d66a3f50 100644
--- a/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java
@@ -40,7 +40,6 @@ package gnu.java.awt.peer.gtk;
import java.awt.Component;
import java.awt.Event;
-import java.awt.MenuItem;
import java.awt.Point;
import java.awt.PopupMenu;
import java.awt.peer.PopupMenuPeer;
diff --git a/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java b/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java
index 9b31a7390..e4147d36c 100644
--- a/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java
@@ -38,8 +38,6 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-import java.awt.Adjustable;
-import java.awt.EventQueue;
import java.awt.Scrollbar;
import java.awt.event.AdjustmentEvent;
import java.awt.peer.ScrollbarPeer;
diff --git a/gnu/java/awt/peer/gtk/GtkToolkit.java b/gnu/java/awt/peer/gtk/GtkToolkit.java
index fdd7e09cb..3f87ca6e6 100644
--- a/gnu/java/awt/peer/gtk/GtkToolkit.java
+++ b/gnu/java/awt/peer/gtk/GtkToolkit.java
@@ -102,6 +102,7 @@ import java.awt.peer.LabelPeer;
import java.awt.peer.ListPeer;
import java.awt.peer.MenuBarPeer;
import java.awt.peer.MenuItemPeer;
+import java.awt.peer.MouseInfoPeer;
import java.awt.peer.MenuPeer;
import java.awt.peer.PanelPeer;
import java.awt.peer.PopupMenuPeer;
@@ -130,37 +131,30 @@ import javax.imageio.spi.IIORegistry;
public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
{
- Hashtable containers = new Hashtable();
- static EventQueue q;
- static Thread mainThread;
+ private static EventQueue q;
static native void gtkInit(int portableNativeSync);
+ static native void gtkMain();
+
+ static native void gtkQuit();
+
static
{
System.loadLibrary("gtkpeer");
-
+
int portableNativeSync;
String portNatSyncProp =
System.getProperty("gnu.classpath.awt.gtk.portable.native.sync");
-
+
if (portNatSyncProp == null)
portableNativeSync = -1; // unset
else if (Boolean.valueOf(portNatSyncProp).booleanValue())
portableNativeSync = 1; // true
else
portableNativeSync = 0; // false
-
+
gtkInit(portableNativeSync);
-
- mainThread = new Thread ("GTK main thread")
- {
- public void run ()
- {
- gtkMain ();
- }
- };
- mainThread.start ();
}
public GtkToolkit ()
@@ -168,6 +162,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
}
public native void beep();
+
private native void getScreenSizeDimensions(int[] xy);
public int checkImage (Image image, int width, int height,
@@ -461,6 +456,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
protected DialogPeer createDialog (Dialog d)
{
+ GtkMainThread.createWindow();
return new GtkDialogPeer (d);
}
@@ -471,6 +467,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
protected FramePeer createFrame (Frame f)
{
+ GtkMainThread.createWindow();
return new GtkFramePeer (f);
}
@@ -531,11 +528,13 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
protected WindowPeer createWindow (Window w)
{
+ GtkMainThread.createWindow();
return new GtkWindowPeer (w);
}
public EmbeddedWindowPeer createEmbeddedWindow (EmbeddedWindow w)
{
+ GtkMainThread.createWindow();
return new GtkEmbeddedWindowPeer (w);
}
@@ -614,8 +613,16 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
DragGestureListener l)
{
if (recognizer.getName().equals("java.awt.dnd.MouseDragGestureRecognizer"))
- return new GtkMouseDragGestureRecognizer(ds, comp, actions, l);
- return null;
+ {
+ GtkMouseDragGestureRecognizer gestureRecognizer
+ = new GtkMouseDragGestureRecognizer(ds, comp, actions, l);
+ gestureRecognizer.registerListeners();
+ return gestureRecognizer;
+ }
+ else
+ {
+ return null;
+ }
}
public Map mapInputMethodHighlight(InputMethodHighlight highlight)
@@ -652,5 +659,11 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
GdkPixbufDecoder.registerSpis(reg);
}
- public static native void gtkMain();
+ protected MouseInfoPeer getMouseInfoPeer()
+ {
+ return new GtkMouseInfoPeer();
+ }
+
+ public native int getMouseNumberOfButtons();
+
} // class GtkToolkit
diff --git a/gnu/java/awt/peer/gtk/GtkWindowPeer.java b/gnu/java/awt/peer/gtk/GtkWindowPeer.java
index d15beacb4..1f340611e 100644
--- a/gnu/java/awt/peer/gtk/GtkWindowPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkWindowPeer.java
@@ -38,13 +38,14 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.Frame;
import java.awt.Graphics;
+import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ComponentEvent;
+import java.awt.event.FocusEvent;
import java.awt.event.PaintEvent;
import java.awt.event.WindowEvent;
import java.awt.peer.WindowPeer;
@@ -70,9 +71,16 @@ public class GtkWindowPeer extends GtkContainerPeer
native void gtkWindowSetTitle (String title);
native void gtkWindowSetResizable (boolean resizable);
native void gtkWindowSetModal (boolean modal);
-
+ native void gtkWindowSetAlwaysOnTop ( boolean alwaysOnTop );
+ native boolean gtkWindowHasFocus();
native void realize ();
+ public void dispose()
+ {
+ super.dispose();
+ GtkMainThread.destroyWindow();
+ }
+
/** Returns the cached width of the AWT window component. */
int getX ()
{
@@ -275,10 +283,13 @@ public class GtkWindowPeer extends GtkContainerPeer
else
q().postEvent (new WindowEvent ((Window) awtComponent, id, opposite));
}
+
+ /**
+ * Update the always-on-top status of the native window.
+ */
public void updateAlwaysOnTop()
{
- // TODO Auto-generated method stub
-
+ gtkWindowSetAlwaysOnTop( ((Window)awtComponent).isAlwaysOnTop() );
}
protected void postExposeEvent (int x, int y, int width, int height)
@@ -299,7 +310,40 @@ public class GtkWindowPeer extends GtkContainerPeer
// TODO Auto-generated method stub
return false;
}
-
+
+ public boolean requestFocus (Component request, boolean temporary,
+ boolean allowWindowFocus, long time)
+ {
+ assert request == awtComponent || isLightweightDescendant(request);
+ boolean retval = false;
+ if (gtkWindowHasFocus())
+ {
+ KeyboardFocusManager kfm =
+ KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ Component currentFocus = kfm.getFocusOwner();
+ if (currentFocus == request)
+ // Nothing to do in this trivial case.
+ retval = true;
+ else
+ {
+ // Requested component is a lightweight descendant of this one
+ // or the actual heavyweight.
+ // Since this (native) component is already focused, we simply
+ // change the actual focus and be done.
+ postFocusEvent(FocusEvent.FOCUS_GAINED, temporary);
+ retval = true;
+ }
+ }
+ else
+ {
+ if (allowWindowFocus)
+ {
+ retval = requestWindowFocus();
+ }
+ }
+ return retval;
+ }
+
public Graphics getGraphics ()
{
Graphics g = super.getGraphics ();
diff --git a/gnu/java/awt/peer/gtk/VolatileImageGraphics.java b/gnu/java/awt/peer/gtk/VolatileImageGraphics.java
index de67b316e..584965593 100644
--- a/gnu/java/awt/peer/gtk/VolatileImageGraphics.java
+++ b/gnu/java/awt/peer/gtk/VolatileImageGraphics.java
@@ -38,25 +38,11 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
-import java.awt.Color;
import java.awt.Graphics;
-import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.Shape;
-import java.awt.font.GlyphVector;
-import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.DataBuffer;
-import java.awt.image.DataBufferInt;
-import java.awt.image.ColorModel;
-import java.awt.image.DirectColorModel;
-import java.awt.image.RenderedImage;
import java.awt.image.ImageObserver;
-import java.util.WeakHashMap;
public class VolatileImageGraphics extends ComponentGraphics
{
diff --git a/gnu/java/awt/peer/qt/QtCheckboxPeer.java b/gnu/java/awt/peer/qt/QtCheckboxPeer.java
index 788e08ee1..acac5e460 100644
--- a/gnu/java/awt/peer/qt/QtCheckboxPeer.java
+++ b/gnu/java/awt/peer/qt/QtCheckboxPeer.java
@@ -1,5 +1,5 @@
/* QtCheckboxPeer.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,7 +37,6 @@ exception statement from your version. */
package gnu.java.awt.peer.qt;
-import java.awt.Rectangle;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.event.ItemEvent;
diff --git a/gnu/java/awt/peer/qt/QtComponentGraphics.java b/gnu/java/awt/peer/qt/QtComponentGraphics.java
index 7395a8e6c..c5c839e32 100644
--- a/gnu/java/awt/peer/qt/QtComponentGraphics.java
+++ b/gnu/java/awt/peer/qt/QtComponentGraphics.java
@@ -1,5 +1,5 @@
/* QtComponentGraphics.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -40,9 +40,7 @@ package gnu.java.awt.peer.qt;
import java.awt.Color;
import java.awt.GraphicsConfiguration;
import java.awt.Graphics;
-import java.awt.Graphics2D;
import java.awt.Rectangle;
-import java.awt.Paint;
/**
* QtComponentPainter is a Graphics2D context for painting directly to AWT
diff --git a/gnu/java/awt/peer/qt/QtComponentPeer.java b/gnu/java/awt/peer/qt/QtComponentPeer.java
index d5662a861..4d7b58c4d 100644
--- a/gnu/java/awt/peer/qt/QtComponentPeer.java
+++ b/gnu/java/awt/peer/qt/QtComponentPeer.java
@@ -1,5 +1,5 @@
/* QtComponentPeer.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,7 +41,6 @@ import java.awt.AWTEvent;
import java.awt.AWTException;
import java.awt.BufferCapabilities;
import java.awt.Component;
-import java.awt.Container;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
diff --git a/gnu/java/awt/peer/qt/QtContainerPeer.java b/gnu/java/awt/peer/qt/QtContainerPeer.java
index 3782d7815..ec04b0567 100644
--- a/gnu/java/awt/peer/qt/QtContainerPeer.java
+++ b/gnu/java/awt/peer/qt/QtContainerPeer.java
@@ -1,5 +1,5 @@
/* QtContainerPeer.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,7 +37,6 @@ exception statement from your version. */
package gnu.java.awt.peer.qt;
-import java.awt.Container;
import java.awt.Component;
import java.awt.Insets;
import java.awt.peer.ContainerPeer;
diff --git a/gnu/java/awt/peer/qt/QtDialogPeer.java b/gnu/java/awt/peer/qt/QtDialogPeer.java
index 0da2e4ebc..23e5c0653 100644
--- a/gnu/java/awt/peer/qt/QtDialogPeer.java
+++ b/gnu/java/awt/peer/qt/QtDialogPeer.java
@@ -1,5 +1,5 @@
/* QtDialogPeer.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,8 +38,6 @@ exception statement from your version. */
package gnu.java.awt.peer.qt;
import java.awt.Dialog;
-import java.awt.MenuBar;
-import java.awt.Rectangle;
import java.awt.peer.DialogPeer;
public class QtDialogPeer extends QtWindowPeer implements DialogPeer
diff --git a/gnu/java/awt/peer/qt/QtEmbeddedWindowPeer.java b/gnu/java/awt/peer/qt/QtEmbeddedWindowPeer.java
index cac12b91a..0f859b78e 100644
--- a/gnu/java/awt/peer/qt/QtEmbeddedWindowPeer.java
+++ b/gnu/java/awt/peer/qt/QtEmbeddedWindowPeer.java
@@ -1,5 +1,5 @@
/* QtEmbeddedWindowPeer.java -- embedded window peer
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,7 +38,6 @@ exception statement from your version. */
package gnu.java.awt.peer.qt;
import java.awt.Component;
-import java.awt.peer.WindowPeer;
import gnu.java.awt.peer.EmbeddedWindowPeer;
/**
diff --git a/gnu/java/awt/peer/qt/QtFontMetrics.java b/gnu/java/awt/peer/qt/QtFontMetrics.java
index e403239e9..2438fcc32 100644
--- a/gnu/java/awt/peer/qt/QtFontMetrics.java
+++ b/gnu/java/awt/peer/qt/QtFontMetrics.java
@@ -1,5 +1,5 @@
/* QtFontMetrics.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,9 +41,6 @@ import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.geom.Rectangle2D;
-import java.awt.font.FontRenderContext;
-import java.awt.font.GlyphVector;
-import java.awt.font.LineMetrics;
public class QtFontMetrics extends FontMetrics
{
diff --git a/gnu/java/awt/peer/qt/QtFontPeer.java b/gnu/java/awt/peer/qt/QtFontPeer.java
index ee88c7dd5..d847a8053 100644
--- a/gnu/java/awt/peer/qt/QtFontPeer.java
+++ b/gnu/java/awt/peer/qt/QtFontPeer.java
@@ -1,5 +1,5 @@
/* QtFontPeer.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -46,7 +46,6 @@ import java.awt.font.LineMetrics;
import java.text.CharacterIterator;
import java.util.Locale;
import java.util.Map;
-import java.awt.peer.FontPeer;
import gnu.java.awt.peer.ClasspathFontPeer;
diff --git a/gnu/java/awt/peer/qt/QtGraphics.java b/gnu/java/awt/peer/qt/QtGraphics.java
index 7b828f7e9..842cbbbf8 100644
--- a/gnu/java/awt/peer/qt/QtGraphics.java
+++ b/gnu/java/awt/peer/qt/QtGraphics.java
@@ -1,5 +1,5 @@
/* QtGraphics.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -58,7 +58,6 @@ import java.awt.Stroke;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
-import java.awt.geom.PathIterator;
import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
diff --git a/gnu/java/awt/peer/qt/QtGraphicsEnvironment.java b/gnu/java/awt/peer/qt/QtGraphicsEnvironment.java
index 142b140cf..15a015922 100644
--- a/gnu/java/awt/peer/qt/QtGraphicsEnvironment.java
+++ b/gnu/java/awt/peer/qt/QtGraphicsEnvironment.java
@@ -1,5 +1,5 @@
/* QtGraphicsEnvironment.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,7 +41,6 @@ import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
-import java.awt.HeadlessException;
import java.awt.image.BufferedImage;
import java.util.Locale;
diff --git a/gnu/java/awt/peer/qt/QtImage.java b/gnu/java/awt/peer/qt/QtImage.java
index 909546435..b6fbb1dca 100644
--- a/gnu/java/awt/peer/qt/QtImage.java
+++ b/gnu/java/awt/peer/qt/QtImage.java
@@ -1,5 +1,5 @@
/* QtImage.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -43,7 +43,6 @@ import java.awt.Image;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.MemoryImageSource;
-import java.awt.image.ImageConsumer;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.io.File;
diff --git a/gnu/java/awt/peer/qt/QtImageConsumer.java b/gnu/java/awt/peer/qt/QtImageConsumer.java
index aec0671f8..7096c21e4 100644
--- a/gnu/java/awt/peer/qt/QtImageConsumer.java
+++ b/gnu/java/awt/peer/qt/QtImageConsumer.java
@@ -1,5 +1,5 @@
/* QtImageConsumer.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,15 +37,10 @@ exception statement from your version. */
package gnu.java.awt.peer.qt;
-import java.awt.Graphics;
-import java.awt.Image;
import java.awt.image.ColorModel;
-import java.awt.image.DirectColorModel;
import java.awt.image.ImageConsumer;
-import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.util.Hashtable;
-import java.util.Vector;
/**
* Helper class to QtImage. Sits and gathers pixels for a QtImage and then
diff --git a/gnu/java/awt/peer/qt/QtImageDirectGraphics.java b/gnu/java/awt/peer/qt/QtImageDirectGraphics.java
index 5a6f3189a..d49084af8 100644
--- a/gnu/java/awt/peer/qt/QtImageDirectGraphics.java
+++ b/gnu/java/awt/peer/qt/QtImageDirectGraphics.java
@@ -1,5 +1,5 @@
/* QtImageDirectGraphics.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,29 +38,10 @@ exception statement from your version. */
package gnu.java.awt.peer.qt;
import java.awt.Color;
-import java.awt.GraphicsConfiguration;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
import java.awt.Image;
-import java.awt.Paint;
-import java.awt.Rectangle;
-import java.util.Stack;
import java.awt.Shape;
-import java.awt.Stroke;
-import java.awt.font.FontRenderContext;
-import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
-import java.awt.geom.PathIterator;
-import java.awt.geom.Arc2D;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Line2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.RoundRectangle2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.BufferedImageOp;
import java.awt.image.ImageObserver;
-import java.awt.image.RenderedImage;
-import java.awt.image.renderable.RenderableImage;
/**
* A QtImagePainter that does an update after every drawing op.
diff --git a/gnu/java/awt/peer/qt/QtImageGraphics.java b/gnu/java/awt/peer/qt/QtImageGraphics.java
index f8a7e51d3..1224d6915 100644
--- a/gnu/java/awt/peer/qt/QtImageGraphics.java
+++ b/gnu/java/awt/peer/qt/QtImageGraphics.java
@@ -1,5 +1,5 @@
/* QtImageGraphics.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -40,9 +40,7 @@ package gnu.java.awt.peer.qt;
import java.awt.Color;
import java.awt.GraphicsConfiguration;
import java.awt.Graphics;
-import java.awt.Graphics2D;
import java.awt.Image;
-import java.awt.Paint;
import java.awt.Rectangle;
import java.util.Stack;
diff --git a/gnu/java/awt/peer/qt/QtMenuBarPeer.java b/gnu/java/awt/peer/qt/QtMenuBarPeer.java
index d8f0d1f88..c91b37f37 100644
--- a/gnu/java/awt/peer/qt/QtMenuBarPeer.java
+++ b/gnu/java/awt/peer/qt/QtMenuBarPeer.java
@@ -1,5 +1,5 @@
/* QtMenuBarPeer.java -- Qt peer for a menu bar.
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -40,7 +40,6 @@ package gnu.java.awt.peer.qt;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.peer.MenuBarPeer;
-import java.util.Vector;
public class QtMenuBarPeer extends QtMenuComponentPeer implements MenuBarPeer
{
diff --git a/gnu/java/awt/peer/qt/QtMenuItemPeer.java b/gnu/java/awt/peer/qt/QtMenuItemPeer.java
index 34753cb35..7658ff078 100644
--- a/gnu/java/awt/peer/qt/QtMenuItemPeer.java
+++ b/gnu/java/awt/peer/qt/QtMenuItemPeer.java
@@ -1,5 +1,5 @@
/* QtMenuItemPeer.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,7 +37,6 @@ exception statement from your version. */
package gnu.java.awt.peer.qt;
-import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.CheckboxMenuItem;
import java.awt.event.ActionEvent;
diff --git a/gnu/java/awt/peer/qt/QtPopupMenuPeer.java b/gnu/java/awt/peer/qt/QtPopupMenuPeer.java
index 81577cc6c..b96c5c510 100644
--- a/gnu/java/awt/peer/qt/QtPopupMenuPeer.java
+++ b/gnu/java/awt/peer/qt/QtPopupMenuPeer.java
@@ -1,5 +1,5 @@
/* QtPopupMenuPeer.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,12 +38,9 @@ exception statement from your version. */
package gnu.java.awt.peer.qt;
import java.awt.Component;
-import java.awt.Menu;
-import java.awt.MenuItem;
import java.awt.Point;
import java.awt.PopupMenu;
import java.awt.Event;
-import java.awt.event.ActionEvent;
import java.awt.peer.PopupMenuPeer;
public class QtPopupMenuPeer extends QtMenuPeer implements PopupMenuPeer
diff --git a/gnu/java/awt/peer/qt/QtScreenDeviceConfiguration.java b/gnu/java/awt/peer/qt/QtScreenDeviceConfiguration.java
index 045cfdf32..c67b55bf4 100644
--- a/gnu/java/awt/peer/qt/QtScreenDeviceConfiguration.java
+++ b/gnu/java/awt/peer/qt/QtScreenDeviceConfiguration.java
@@ -1,5 +1,5 @@
/* QtScreenDeviceConfiguration.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,11 +37,9 @@ exception statement from your version. */
package gnu.java.awt.peer.qt;
-import java.awt.DisplayMode;
import java.awt.ImageCapabilities;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
-import java.awt.GraphicsConfigTemplate;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
diff --git a/gnu/java/awt/peer/qt/QtScrollPanePeer.java b/gnu/java/awt/peer/qt/QtScrollPanePeer.java
index 02fa8fb22..c3731cbd5 100644
--- a/gnu/java/awt/peer/qt/QtScrollPanePeer.java
+++ b/gnu/java/awt/peer/qt/QtScrollPanePeer.java
@@ -1,5 +1,5 @@
/* QtScrollPanePeer.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,7 +38,6 @@ exception statement from your version. */
package gnu.java.awt.peer.qt;
import java.awt.Adjustable;
-import java.awt.Dimension;
import java.awt.Insets;
import java.awt.ScrollPane;
import java.awt.peer.ScrollPanePeer;
diff --git a/gnu/java/awt/peer/qt/QtToolkit.java b/gnu/java/awt/peer/qt/QtToolkit.java
index a8bfb1b51..511676938 100644
--- a/gnu/java/awt/peer/qt/QtToolkit.java
+++ b/gnu/java/awt/peer/qt/QtToolkit.java
@@ -1,5 +1,5 @@
/* QtToolkit.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,18 +37,16 @@ exception statement from your version. */
package gnu.java.awt.peer.qt;
-import gnu.classpath.Configuration;
import gnu.java.awt.EmbeddedWindow;
import gnu.java.awt.peer.ClasspathFontPeer;
import gnu.java.awt.peer.EmbeddedWindowPeer;
-import java.awt.AWTEvent;
+
import java.awt.AWTException;
import java.awt.Button;
import java.awt.Canvas;
import java.awt.Checkbox;
import java.awt.CheckboxMenuItem;
import java.awt.Choice;
-import java.awt.Component;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.EventQueue;
@@ -67,18 +65,13 @@ import java.awt.TextField;
import java.awt.FileDialog;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
-import java.awt.HeadlessException;
import java.awt.PopupMenu;
import java.awt.PrintJob;
import java.awt.Scrollbar;
import java.awt.ScrollPane;
-import java.awt.Toolkit;
import java.awt.Window;
import java.awt.datatransfer.Clipboard;
import java.awt.dnd.DragGestureEvent;
-import java.awt.dnd.DragGestureListener;
-import java.awt.dnd.DragGestureRecognizer;
-import java.awt.dnd.DragSource;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.event.AWTEventListener;
import java.awt.image.ColorModel;
@@ -90,37 +83,29 @@ import java.awt.peer.ButtonPeer;
import java.awt.peer.FontPeer;
import java.awt.peer.PanelPeer;
import java.awt.peer.CanvasPeer;
-import java.awt.peer.FramePeer;
+import java.awt.peer.FramePeer;
import java.awt.peer.PopupMenuPeer;
import java.awt.peer.CheckboxMenuItemPeer;
import java.awt.peer.LabelPeer;
import java.awt.peer.RobotPeer;
import java.awt.peer.CheckboxPeer;
-import java.awt.peer.LightweightPeer;
import java.awt.peer.ScrollPanePeer;
-import java.awt.peer.ChoicePeer;
+import java.awt.peer.ChoicePeer;
import java.awt.peer.ListPeer;
import java.awt.peer.ScrollbarPeer;
-import java.awt.peer.ComponentPeer;
import java.awt.peer.MenuBarPeer;
import java.awt.peer.TextAreaPeer;
-import java.awt.peer.ContainerPeer;
-import java.awt.peer.MenuComponentPeer;
-import java.awt.peer.TextComponentPeer;
import java.awt.peer.DialogPeer;
import java.awt.peer.MenuItemPeer;
import java.awt.peer.TextFieldPeer;
import java.awt.peer.FileDialogPeer;
import java.awt.peer.MenuPeer;
import java.awt.peer.WindowPeer;
-import java.awt.font.FontRenderContext;
import java.io.InputStream;
import java.net.URL;
-import java.text.AttributedString;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
-import javax.imageio.spi.IIORegistry;
import gnu.java.awt.ClasspathToolkit;
diff --git a/gnu/java/awt/peer/qt/QtVolatileImage.java b/gnu/java/awt/peer/qt/QtVolatileImage.java
index 0ec61deb3..c81bb2a09 100644
--- a/gnu/java/awt/peer/qt/QtVolatileImage.java
+++ b/gnu/java/awt/peer/qt/QtVolatileImage.java
@@ -1,5 +1,5 @@
/* QtVolatileImage.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -47,15 +47,11 @@ import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.MemoryImageSource;
-import java.awt.image.ImageConsumer;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.VolatileImage;
-import java.io.File;
-import java.io.IOException;
import java.util.Hashtable;
import java.util.WeakHashMap;
-import java.util.Vector;
/**
* QtVolatileImage - wraps a QImage
diff --git a/gnu/java/awt/dnd/peer/gtk/GtkDropTargetPeer.java b/gnu/java/awt/peer/x/XDialogPeer.java
index d7ed26dae..45ad24d67 100644
--- a/gnu/java/awt/dnd/peer/gtk/GtkDropTargetPeer.java
+++ b/gnu/java/awt/peer/x/XDialogPeer.java
@@ -1,4 +1,4 @@
-/* GtkDropTargetPeer.java --
+/* XDialogPeer.java -- The peer for AWT dialogs
Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -36,25 +36,26 @@ obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-package gnu.java.awt.dnd.peer.gtk;
+package gnu.java.awt.peer.x;
-import java.awt.dnd.DropTarget;
-import java.awt.dnd.peer.DropTargetPeer;
+import java.awt.Dialog;
+import java.awt.peer.DialogPeer;
-public class GtkDropTargetPeer
- implements DropTargetPeer
+public class XDialogPeer
+ extends XWindowPeer
+ implements DialogPeer
{
- public void addDropTarget(DropTarget target)
+ XDialogPeer(Dialog target)
{
- // FIXME: Not Implemented
-
+ super(target);
}
- public void removeDropTarget(DropTarget target)
+ public void setResizable(boolean resizeable)
{
- // FIXME: Not Implemented
-
}
+ public void setTitle(String title)
+ {
+ }
}
diff --git a/gnu/java/awt/peer/x/XEventPump.java b/gnu/java/awt/peer/x/XEventPump.java
index bd1ef08ce..870edf379 100644
--- a/gnu/java/awt/peer/x/XEventPump.java
+++ b/gnu/java/awt/peer/x/XEventPump.java
@@ -207,9 +207,9 @@ public class XEventPump
System.err.println("Setting size on AWT window: " + c.width()
+ ", " + c.height() + ", " + awtWindow.getWidth()
+ ", " + awtWindow.getHeight());
- ((XFramePeer) awtWindow.getPeer()).callback = true;
+ ((XWindowPeer) awtWindow.getPeer()).callback = true;
awtWindow.setSize(c.width(), c.height());
- ((XFramePeer) awtWindow.getPeer()).callback = false;
+ ((XWindowPeer) awtWindow.getPeer()).callback = false;
}
break;
case Expose.CODE:
diff --git a/gnu/java/awt/peer/x/XFontPeer.java b/gnu/java/awt/peer/x/XFontPeer.java
index 8a499db1a..fd293d8dd 100644
--- a/gnu/java/awt/peer/x/XFontPeer.java
+++ b/gnu/java/awt/peer/x/XFontPeer.java
@@ -694,7 +694,8 @@ public class XFontPeer
}
String protoType = fontProperties.getProperty(key.toString());
- return protoType.replaceFirst("%d", String.valueOf(size));
+ int s = validSize(size);
+ return protoType.replaceFirst("%d", String.valueOf(s * 10));
}
/**
@@ -724,6 +725,31 @@ public class XFontPeer
}
/**
+ * Translates an arbitrary point size to a size that is typically available
+ * on an X server. These are the sizes 8, 10, 12, 14, 18 and 24.
+ *
+ * @param size the queried size
+ * @return the real available size
+ */
+ private static final int validSize(int size)
+ {
+ int val;
+ if (size <= 9)
+ val = 8;
+ else if (size <= 11)
+ val = 10;
+ else if (size <= 13)
+ val = 12;
+ else if (size <= 17)
+ val = 14;
+ else if (size <= 23)
+ val = 18;
+ else
+ val = 24;
+ return val;
+ }
+
+ /**
* Returns the X Font reference. This lazily loads the font when first
* requested.
*
diff --git a/gnu/java/awt/peer/x/XFramePeer.java b/gnu/java/awt/peer/x/XFramePeer.java
index 1d34b1a81..439a2a7bb 100644
--- a/gnu/java/awt/peer/x/XFramePeer.java
+++ b/gnu/java/awt/peer/x/XFramePeer.java
@@ -46,56 +46,25 @@ import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Insets;
+import java.awt.MenuBar;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.PaintEvent;
import java.awt.event.WindowEvent;
+import java.awt.peer.FramePeer;
import gnu.java.awt.peer.swing.SwingFramePeer;
import gnu.x11.Window;
import gnu.x11.event.Event;
public class XFramePeer
- extends SwingFramePeer
+ extends XWindowPeer
+ implements FramePeer
{
- private static int standardSelect = Event.BUTTON_PRESS_MASK
- | Event.BUTTON_RELEASE_MASK
- | Event.POINTER_MOTION_MASK
- //| Event.RESIZE_REDIRECT_MASK
- | Event.EXPOSURE_MASK
- //| Event.PROPERTY_CHANGE_MASK
- | Event.STRUCTURE_NOTIFY_MASK
- | Event.KEY_PRESS_MASK
- | Event.KEY_RELEASE_MASK
- ;
-
- /**
- * The X window.
- */
- private Window xwindow;
-
- /**
- * Indicates if we are in callback mode, that is when a property (like size)
- * is changed in reponse to a request from the X server and doesn't need
- * to be propagated back to the X server.
- */
- boolean callback = false;
-
- public XFramePeer(Frame frame)
+ XFramePeer(Frame f)
{
- super(frame);
- XGraphicsDevice dev = XToolkit.getDefaultDevice();
-
- // TODO: Maybe initialize lazily in show().
- int x = Math.max(frame.getX(), 0);
- int y = Math.max(frame.getY(), 0);
- int w = Math.max(frame.getWidth(), 1);
- int h = Math.max(frame.getHeight(), 1);
- xwindow = new Window(dev.getDisplay().default_root, x, y, w, h);
- xwindow.create();
- xwindow.select_input(standardSelect);
- dev.getEventPump().registerWindow(xwindow, frame);
+ super(f);
}
public void setIconImage(Image image)
@@ -104,6 +73,12 @@ public class XFramePeer
throw new UnsupportedOperationException("Not yet implemented.");
}
+ public void setMenuBar(MenuBar mb)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
public void setResizable(boolean resizable)
{
// TODO: Implement this.
@@ -124,198 +99,42 @@ public class XFramePeer
public void setState(int state)
{
- // FIXME: Implement this.
+ // TODO: Implement this.
throw new UnsupportedOperationException("Not yet implemented.");
}
public void setMaximizedBounds(Rectangle r)
{
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented.");
- }
-
- public void setBoundsPrivate(int x, int y, int width, int height)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented.");
- }
-
- public void toBack()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented.");
- }
-
- public void toFront()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented.");
- }
-
- public void updateAlwaysOnTop()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented.");
- }
-
- public boolean requestWindowFocus()
- {
- // FIXME: Implement this.
+ // TODO: Implement this.
throw new UnsupportedOperationException("Not yet implemented.");
}
-
- public Point getLocationOnScreen()
- {
- return new Point(xwindow.x, xwindow.y);
- }
-
+
/**
- * Returns a XGraphics suitable for drawing on this frame.
- *
- * @return a XGraphics suitable for drawing on this frame
+ * Check if this frame peer supports being restacked.
+ *
+ * @return true if this frame peer can be restacked,
+ * false otherwise
+ * @since 1.5
*/
- public Graphics getGraphics()
- {
- return new XGraphics(xwindow);
- }
-
- public Image createImage(int w, int h)
+ public boolean isRestackSupported()
{
- return new XImage(w, h);
- }
-
- /**
- * Sets the visibility state of the component. This is called by
- * {@link Component#setVisible(boolean)}.
- *
- * This is implemented to call setVisible() on the Swing component.
- *
- * @param visible <code>true</code> to make the component visible,
- * <code>false</code> to make it invisible
- */
- public void setVisible(boolean visible)
- {
- if (visible)
- show();
- else
- hide();
- }
-
- /**
- * Makes the component visible. This is called by {@link Component#show()}.
- *
- * This is implemented to call setVisible(true) on the Swing component.
- */
- public void show()
- {
-// // Prevent ResizeRedirect events.
-// //xwindow.select_input(noResizeRedirectSelect);
-// Window.Attributes atts = new Window.Attributes();
-// atts.set_override_redirect(true);
-// xwindow.change_attributes(atts);
-
- // Prevent ResizeRedirect events.
- //xwindow.select_input(Event.NO_EVENT_MASK);
- //xwindow.select_input(noResizeRedirectSelect);
-
- xwindow.map();
- EventQueue eq = XToolkit.getDefaultToolkit().getSystemEventQueue();
- java.awt.Window w = (java.awt.Window) super.awtComponent;
- eq.postEvent(new WindowEvent(w, WindowEvent.WINDOW_OPENED));
- eq.postEvent(new PaintEvent(w, PaintEvent.PAINT,
- new Rectangle(0, 0, w.getWidth(),
- w.getHeight())));
-
-// // Reset input selection.
-// atts.set_override_redirect(false);
-// xwindow.change_attributes(atts);
- }
-
- /**
- * Makes the component invisible. This is called from
- * {@link Component#hide()}.
- *
- * This is implemented to call setVisible(false) on the Swing component.
- */
- public void hide()
- {
- xwindow.unmap();
- }
-
- /**
- * Notifies the peer that the bounds of this component have changed. This
- * is called by {@link Component#reshape(int, int, int, int)}.
- *
- * This is implemented to call setBounds() on the Swing component.
- *
- * @param x the X coordinate of the upper left corner of the component
- * @param y the Y coordinate of the upper left corner of the component
- * @param width the width of the component
- * @param height the height of the component
- */
- public void reshape(int x, int y, int width, int height)
- {
-// if (callback)
-// return;
-
- // Prevent ResizeRedirect events.
-// //xwindow.select_input(noResizeRedirectSelect);
-// Window.Attributes atts = new Window.Attributes();
-// atts.set_override_redirect(true);
-// xwindow.change_attributes(atts);
-
- // Need to substract insets because AWT size is including insets,
- // and X size is excuding insets.
- Insets i = insets();
- xwindow.move_resize(x - i.left, y - i.right, width - i.left - i.right,
- height - i.top - i.bottom);
-
- // Reset input selection.
-// atts = new Window.Attributes();
-// atts.set_override_redirect(false);
-// xwindow.change_attributes(atts);
- }
-
- public Insets insets()
- {
- Insets i = new Insets(0, 0, 0, 0);
-// Window.GeometryReply g = xwindow.geometry();
-// int b = g.border_width();
-// Insets i = new Insets(b, b, b, b);
-// Window.WMSizeHints wmSize = xwindow.wm_normal_hints();
-// if (wmSize != null)
-// {
-// i.left = wmSize.x() - g.x();
-// i.right = wmSize.width() - g.width() - i.left ;
-// i.top = wmSize.y() - g.y();
-// i.bottom = wmSize.height() - g.height() - i.top;
-// }
-// System.err.println("insets: " + i);
- return i;
- }
-
- /**
- * Returns the font metrics for the specified font.
- *
- * @return the font metrics for the specified font
- */
- public FontMetrics getFontMetrics(Font font)
- {
- XFontPeer fontPeer = (XFontPeer) font.getPeer();
- return fontPeer.getFontMetrics(font);
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
}
-
+
/**
- * Unregisters the window in the event pump when it is closed.
+ * Sets the bounds of this frame peer.
+ *
+ * @param x the new x co-ordinate
+ * @param y the new y co-ordinate
+ * @param width the new width
+ * @param height the new height
+ * @since 1.5
*/
- protected void finalize()
+ public void setBoundsPrivate(int x, int y, int width, int height)
{
- XGraphicsDevice dev = XToolkit.getDefaultDevice();
- dev.getEventPump().unregisterWindow(xwindow);
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
}
- public Rectangle getBounds()
- {
- return new Rectangle(xwindow.x, xwindow.y, xwindow.width, xwindow.height);
- }
}
diff --git a/gnu/java/awt/peer/x/XGraphics.java b/gnu/java/awt/peer/x/XGraphics.java
index 81168797c..134d7d330 100644
--- a/gnu/java/awt/peer/x/XGraphics.java
+++ b/gnu/java/awt/peer/x/XGraphics.java
@@ -38,40 +38,33 @@ exception statement from your version. */
package gnu.java.awt.peer.x;
+import gnu.x11.Colormap;
+import gnu.x11.Data;
+import gnu.x11.Display;
import gnu.x11.Drawable;
import gnu.x11.GC;
import gnu.x11.Pixmap;
import gnu.x11.Point;
+import gnu.x11.image.ZPixmap;
import java.awt.AWTError;
import java.awt.Color;
-import java.awt.Composite;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.GraphicsConfiguration;
import java.awt.Image;
-import java.awt.Paint;
import java.awt.Rectangle;
-import java.awt.RenderingHints;
import java.awt.Shape;
-import java.awt.Stroke;
-import java.awt.RenderingHints.Key;
-import java.awt.font.FontRenderContext;
-import java.awt.font.GlyphVector;
-import java.awt.geom.AffineTransform;
+import java.awt.Toolkit;
+import java.awt.Transparency;
import java.awt.image.BufferedImage;
-import java.awt.image.BufferedImageOp;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
-import java.awt.image.RenderedImage;
-import java.awt.image.renderable.RenderableImage;
import java.text.AttributedCharacterIterator;
-import java.util.Map;
+import java.util.HashMap;
public class XGraphics
- extends Graphics2D
+ extends Graphics
implements Cloneable
{
@@ -111,6 +104,11 @@ public class XGraphics
*/
private boolean disposed = false;
+ // TODO: Workaround for limitation in current Escher.
+ private Pixmap.Format pixmapFormat;
+ private int imageByteOrder;
+ private int pixelByteCount;
+
/**
* Creates a new XGraphics on the specified X Drawable.
*
@@ -123,6 +121,11 @@ public class XGraphics
translateX = 0;
translateY = 0;
clip = new Rectangle(0, 0, d.width, d.height);
+
+ Display display = xdrawable.display;
+ pixmapFormat = display.default_pixmap_format;
+ imageByteOrder = display.image_byte_order;
+ pixelByteCount = pixmapFormat.bits_per_pixel () / 8;
}
/**
@@ -147,7 +150,6 @@ public class XGraphics
{
clip.x -= x;
clip.y -= y;
- setClip(clip);
}
}
@@ -171,7 +173,18 @@ public class XGraphics
{
if (c != null)
{
- xgc.set_foreground(c.getRGB());
+ XToolkit tk = (XToolkit) Toolkit.getDefaultToolkit();
+ HashMap colorMap = tk.colorMap;
+ gnu.x11.Color col = (gnu.x11.Color) colorMap.get(c);
+ if (col == null)
+ {
+ Colormap map = xdrawable.display.default_colormap;
+ col = map.alloc_color (c.getRed() * 256,
+ c.getGreen() * 256,
+ c.getBlue() * 256);
+ colorMap.put(c, col);
+ }
+ xgc.set_foreground(col);
foreground = c;
}
}
@@ -257,7 +270,7 @@ public class XGraphics
computeIntersection(x, y, width, height, clip);
}
// Update the X clip setting.
- setClip(clip.x, clip.y, clip.width, clip.height);
+ setXClip(clip.x, clip.y, clip.width, clip.height);
}
/**
@@ -282,9 +295,19 @@ public class XGraphics
}
else
{
- hit = clip.intersects(x, y, w, h);
+ // It's easier to determine if the rectangle lies outside the clip,
+ // so we determine that and reverse the result (if it's not completely
+ // outside, it most likely hits the clip rectangle).
+ int x2 = x + w;
+ int y2 = y + h;
+ int clipX2 = clip.x + clip.width;
+ int clipY2 = clip.y + clip.height;
+ boolean outside = (x < clip.x && x2 < clip.x) // Left.
+ || (x > clipX2 && x2 > clipX2) // Right.
+ || (y < clip.y && y2 < clip.y) // Top.
+ || (y > clipY2 && y2 > clipY2); // Bottom.
+ hit = ! outside;
}
- //System.err.println("hitClip: " + hit);
return hit;
}
@@ -294,10 +317,23 @@ public class XGraphics
clip.setBounds(x, y, width, height);
else
clip = new Rectangle(x, y, width, height);
+ setXClip(clip.x, clip.y, clip.width, clip.height);
+ }
+ /**
+ * Sets the clip on the X server GC. The coordinates are not yet translated,
+ * this will be performed by the X server.
+ *
+ * @param x the clip, X coordinate
+ * @param y the clip, Y coordinate
+ * @param w the clip, width
+ * @param h the clip, height
+ */
+ private void setXClip(int x, int y, int w, int h)
+ {
gnu.x11.Rectangle[] clipRects = new gnu.x11.Rectangle[] {
- new gnu.x11.Rectangle(x, y, width, height) };
- xgc.set_clip_rectangles(translateX, translateY, clipRects, GC.UN_SORTED);
+ new gnu.x11.Rectangle(x, y, w, h) };
+ xgc.set_clip_rectangles(translateX, translateY, clipRects, GC.YX_BANDED);
}
public Shape getClip()
@@ -309,33 +345,44 @@ public class XGraphics
/**
* Sets the current clip.
*
- * @param clip the clip to set
+ * @param c the clip to set
*/
- public void setClip(Shape clip)
+ public void setClip(Shape c)
{
- if (clip != null)
+ if (c != null)
{
Rectangle b;
- if (clip instanceof Rectangle)
+ if (c instanceof Rectangle)
{
- b = (Rectangle) clip;
+ b = (Rectangle) c;
}
else
{
- b = clip.getBounds();
+ b = c.getBounds();
}
- setClip(b.x, b.y, b.width, b.height);
+ clip.setBounds(b);
+ setXClip(b.x, b.y, b.width, b.height);
}
else
{
- setClip(0, 0, xdrawable.width, xdrawable.height);
+ clip.setBounds(0, 0, xdrawable.width, xdrawable.height);
+ setXClip(0, 0, xdrawable.width, xdrawable.height);
}
}
public void copyArea(int x, int y, int width, int height, int dx, int dy)
{
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
+ // Clip and translate src rectangle.
+ int srcX = Math.min(Math.max(x, clip.x), clip.x + clip.width)
+ + translateX;
+ int srcY = Math.min(Math.max(y, clip.y), clip.y + clip.height)
+ + translateY;
+ int srcWidth = Math.min(Math.max(x + width, clip.x),
+ clip.x + clip.width) - x;
+ int srcHeight = Math.min(Math.max(y + height, clip.y),
+ clip.y + clip.height) - y;
+ xdrawable.copy_area(xdrawable, xgc, srcX, srcY, srcWidth, srcHeight,
+ srcX + dx, srcY + dy);
}
/**
@@ -498,32 +545,51 @@ public class XGraphics
xdrawable.copy_area(pm, xgc, 0, 0, pm.width, pm.height,
x + translateX, y + translateY);
}
-// else if (image instanceof BufferedImage)
-// {
-// BufferedImage bufferedImage = (BufferedImage) image;
-// Raster raster = bufferedImage.getData();
-// int w = bufferedImage.getWidth();
-// int h = bufferedImage.getHeight();
-// // Push data to X server.
-// ZPixmap zPixmap = new ZPixmap(xdrawable.display, w, h,
-// xdrawable.display.default_pixmap_format);
-// System.err.println("data buffer length: " + zPixmap.data.length);
-// int[] pixel = new int[4];
-// for (int tx = 0; tx < w; tx++)
-// {
-// for (int ty = 0; ty < h; ty++)
-// {
-// pixel = raster.getPixel(tx, ty, pixel);
-//// System.err.print("r: " + pixel[0]);
-//// System.err.print(", g: " + pixel[1]);
-//// System.err.println(", b: " + pixel[2]);
-// zPixmap.set_red(tx, ty, pixel[0]);
-// zPixmap.set_green(tx, ty, pixel[1]);
-// zPixmap.set_blue(tx, ty, pixel[2]);
-// }
-// }
-// xdrawable.put_image(xgc, zPixmap, x, y);
-// }
+ else if (image instanceof BufferedImage
+ && ((BufferedImage) image).getTransparency() != Transparency.OPAQUE)
+ {
+ BufferedImage bi = (BufferedImage) image;
+ int width = bi.getWidth();
+ int height = bi.getHeight();
+ Data img = xdrawable.image(x + translateX, y + translateY,
+ width, height, 0xFFFFFFFF, 2);
+
+ // Compute line byte count.
+ int lineBitCount = width * pixmapFormat.bits_per_pixel ();
+ int rem = lineBitCount % pixmapFormat.scanline_pad ();
+ int linePadCount = lineBitCount / pixmapFormat.scanline_pad ()
+ + (rem == 0 ? 0 : 1);
+ int lineByteCount = linePadCount * pixmapFormat.scanline_pad () / 8;
+
+ // Composite source and destination pixel data.
+ int[] trgb = new int[3]; // The device rgb pixels.
+ for (int yy = 0; yy < height; yy++)
+ {
+ for (int xx = 0; xx < width; xx++)
+ {
+ getRGB(xx, yy, img, trgb, lineByteCount);
+ int srgb = bi.getRGB(xx, yy);
+ float alpha = ((srgb >> 24) & 0xff) / 256F;
+ float tAlpha = 1.F - alpha;
+ int red = (srgb >> 16) & 0xFF;
+ int green = (srgb >> 8) & 0xFF;
+ int blue = (srgb) & 0xFF;
+ trgb[0] = (int) (trgb[0] * tAlpha + red * alpha);
+ trgb[1] = (int) (trgb[1] * tAlpha + green * alpha);
+ trgb[2] = (int) (trgb[2] * tAlpha + blue * alpha);
+ setRGB(xx, yy, img, trgb, lineByteCount);
+ }
+ }
+
+ // Now we have the transparent image composited onto the target
+ // Image, now we only must copy it to the Drawable.
+ ZPixmap pm = new ZPixmap(xdrawable.display);
+ pm.width = width;
+ pm.height = height;
+ pm.init();
+ System.arraycopy(img.data, 32, pm.data, 0, img.data.length - 32);
+ xdrawable.put_image(xgc, pm, x + translateX, y + translateY);
+ }
else
{
// Pre-render the image into an XImage.
@@ -538,6 +604,59 @@ public class XGraphics
return true;
}
+ /**
+ * Helper method to work around limitation in the current Escher impl.
+ *
+ * @param x the x position
+ * @param y the y position
+ * @param img the image data
+ * @param rgb an 3-size array that holds the rgb values on method exit
+ */
+ private void getRGB(int x, int y, Data img, int[] rgb, int lineByteCount)
+ {
+ // TODO: Does this also work on non-RGB devices?
+ int i = y * lineByteCount + pixelByteCount * x;
+ if (imageByteOrder == gnu.x11.image.Image.LSB_FIRST)
+ {//if (i >= 5716-33) System.err.println("lbc: " + lineByteCount + ", " + pixelByteCount);
+ rgb[2] = img.data[32 + i];
+ rgb[1] = img.data[32 + i + 1];
+ rgb[0] = img.data[32 + i + 2];
+ }
+ else
+ { // MSB_FIRST
+ rgb[0] = img.data[32 + i];
+ rgb[1] = img.data[32 + i + 1];
+ rgb[2] = img.data[32 + i + 2];
+ }
+
+ }
+
+ /**
+ * Helper method to work around limitation in the current Escher impl.
+ *
+ * @param x the x position
+ * @param y the y position
+ * @param img the image data
+ * @param rgb an 3-size array that holds the rgb values on method exit
+ */
+ private void setRGB(int x, int y, Data img, int[] rgb, int lineByteCount)
+ {
+ // TODO: Does this also work on non-RGB devices?
+ int i = y * lineByteCount + pixelByteCount * x;
+ if (imageByteOrder == gnu.x11.image.Image.LSB_FIRST)
+ {
+ img.data[32 + i] = (byte) rgb[2];
+ img.data[32 + i + 1] = (byte) rgb[1];
+ img.data[32 + i + 2] = (byte) rgb[0];
+ }
+ else
+ { // MSB_FIRST
+ img.data[32 + i] = (byte) rgb[0];
+ img.data[32 + i + 1] = (byte) rgb[1];
+ img.data[32 + i + 2] = (byte) rgb[2];
+ }
+ }
+
public boolean drawImage(Image image, int x, int y, int width, int height,
ImageObserver observer)
{
@@ -563,16 +682,41 @@ public class XGraphics
int sx1, int sy1, int sx2, int sy2,
ImageObserver observer)
{
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
+ return drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null,
+ observer);
}
public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,
int sx1, int sy1, int sx2, int sy2, Color bgcolor,
ImageObserver observer)
{
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
+
+ // FIXME: What to do with bgcolor?
+
+ // Scale the image.
+ int sw = image.getWidth(observer);
+ int sh = image.getHeight(observer);
+ double scaleX = Math.abs(dx2 - dx1) / (double) Math.abs(sx2 - sx1);
+ double scaleY = Math.abs(dy2 - dy1) / (double) Math.abs(sy2 - sy1);
+ Image scaled = image.getScaledInstance((int) (scaleX * sw),
+ (int) (scaleY * sh),
+ Image.SCALE_FAST);
+
+ // Scaled source coordinates.
+ int sx1s = (int) (scaleX * Math.min(sx1, sx2));
+ int sx2s = (int) (scaleX * Math.max(sx1, sx2));
+
+ // Temporarily clip to the target rectangle.
+ Rectangle old = clip;
+ clipRect(dx1, dy1, dx2 - dx1, dy2 - dy1);
+
+ // Draw scaled image.
+ boolean res = drawImage(scaled, dx1 - sx1s, dy1 - sx2s, observer);
+
+ // Reset clip.
+ setClip(old);
+
+ return res;
}
/**
@@ -580,221 +724,14 @@ public class XGraphics
*/
public void dispose()
{
- xdrawable.display.flush();
if (! disposed)
{
xgc.free();
+ xdrawable.display.flush();
disposed = true;
}
}
- // Additional Graphics2D methods.
-
- public void draw(Shape shape)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public boolean drawImage(Image image, AffineTransform xform, ImageObserver obs)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void drawImage(BufferedImage image, BufferedImageOp op, int x, int y)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void drawRenderedImage(RenderedImage image, AffineTransform xform)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void drawRenderableImage(RenderableImage image, AffineTransform xform)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void drawString(String text, float x, float y)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void drawString(AttributedCharacterIterator iterator, float x, float y)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void fill(Shape shape)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public boolean hit(Rectangle rect, Shape text, boolean onStroke)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public GraphicsConfiguration getDeviceConfiguration()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void setComposite(Composite comp)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void setPaint(Paint paint)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void setStroke(Stroke stroke)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void setRenderingHint(Key hintKey, Object hintValue)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public Object getRenderingHint(Key hintKey)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void setRenderingHints(Map hints)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void addRenderingHints(Map hints)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public RenderingHints getRenderingHints()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void translate(double tx, double ty)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void rotate(double theta)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void rotate(double theta, double x, double y)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void scale(double scaleX, double scaleY)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void shear(double shearX, double shearY)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void transform(AffineTransform Tx)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void setTransform(AffineTransform Tx)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public AffineTransform getTransform()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public Paint getPaint()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public Composite getComposite()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void setBackground(Color color)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public Color getBackground()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public Stroke getStroke()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void clip(Shape s)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public FontRenderContext getFontRenderContext()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void drawGlyphVector(GlyphVector g, float x, float y)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
-
// Additional helper methods.
/**
@@ -806,18 +743,18 @@ public class XGraphics
{
XGraphics copy = (XGraphics) super.clone();
copy.xgc = xgc.copy();
-
- // Save the original clip.
if (clip != null)
- copy.clip = new Rectangle(clip);
+ {
+ copy.clip = new Rectangle(clip);
+ copy.setXClip(clip.x, clip.y, clip.width, clip.height);
+ }
return copy;
}
catch (CloneNotSupportedException ex)
{
- AWTError err = new AWTError("Error while cloning XGraphics");
- err.initCause(ex);
- throw err;
+ assert false;
}
+ return null;
}
/**
diff --git a/gnu/java/awt/peer/x/XGraphicsEnvironment.java b/gnu/java/awt/peer/x/XGraphicsEnvironment.java
index 707b44c38..65383a6cb 100644
--- a/gnu/java/awt/peer/x/XGraphicsEnvironment.java
+++ b/gnu/java/awt/peer/x/XGraphicsEnvironment.java
@@ -80,7 +80,7 @@ public class XGraphicsEnvironment
* environment. If there is no configuration, then there is one
* default device initialized with the local main X device.
*/
- XGraphicsEnvironment()
+ public XGraphicsEnvironment()
{
// Initiliaze the devices.
Properties props = new Properties();
diff --git a/gnu/java/awt/peer/x/XImage.java b/gnu/java/awt/peer/x/XImage.java
index 28bc6b90a..b9e993628 100644
--- a/gnu/java/awt/peer/x/XImage.java
+++ b/gnu/java/awt/peer/x/XImage.java
@@ -43,9 +43,9 @@ import gnu.x11.Pixmap;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
-import java.awt.Toolkit;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
+import java.util.Hashtable;
public class XImage
extends Image
@@ -53,10 +53,12 @@ public class XImage
Pixmap pixmap;
+ private Hashtable properties;
+
XImage(int w, int h)
{
- XToolkit tk = (XToolkit) Toolkit.getDefaultToolkit();
- GraphicsEnvironment env = tk.getLocalGraphicsEnvironment();
+ GraphicsEnvironment env =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
XGraphicsDevice dev = (XGraphicsDevice) env.getDefaultScreenDevice();
pixmap = new Pixmap(dev.getDisplay(), w, h);
}
@@ -90,8 +92,10 @@ public class XImage
public Object getProperty(String name, ImageObserver observer)
{
- // TODO: Implement this.
- throw new UnsupportedOperationException("Not yet implemented.");
+ Object val = null;
+ if (properties != null)
+ val = properties.get(val);
+ return val;
}
public void flush()
diff --git a/gnu/java/awt/peer/x/XToolkit.java b/gnu/java/awt/peer/x/XToolkit.java
index 05e8a5963..a286fd6f0 100644
--- a/gnu/java/awt/peer/x/XToolkit.java
+++ b/gnu/java/awt/peer/x/XToolkit.java
@@ -67,11 +67,11 @@ import java.awt.ScrollPane;
import java.awt.Scrollbar;
import java.awt.TextArea;
import java.awt.TextField;
+import java.awt.Transparency;
import java.awt.Window;
import java.awt.datatransfer.Clipboard;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.peer.DragSourceContextPeer;
-import java.awt.font.FontRenderContext;
import java.awt.im.InputMethodHighlight;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
@@ -101,12 +101,12 @@ import java.awt.peer.ScrollbarPeer;
import java.awt.peer.TextAreaPeer;
import java.awt.peer.TextFieldPeer;
import java.awt.peer.WindowPeer;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
-import java.text.AttributedString;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
@@ -114,6 +114,7 @@ import java.util.WeakHashMap;
import javax.imageio.ImageIO;
+import gnu.classpath.SystemProperties;
import gnu.java.awt.ClasspathToolkit;
import gnu.java.awt.EmbeddedWindow;
import gnu.java.awt.peer.ClasspathFontPeer;
@@ -131,7 +132,10 @@ public class XToolkit
*/
static boolean DEBUG = false;
- private XGraphicsEnvironment env;
+ /**
+ * Maps AWT colors to X colors.
+ */
+ HashMap colorMap = new HashMap();
/**
* The system event queue.
@@ -155,14 +159,14 @@ public class XToolkit
public XToolkit()
{
- System.setProperty("gnu.javax.swing.noGraphics2D", "true");
+ SystemProperties.setProperty("gnu.javax.swing.noGraphics2D", "true");
+ SystemProperties.setProperty("java.awt.graphicsenv",
+ "gnu.java.awt.peer.x.XGraphicsEnvironment");
}
public GraphicsEnvironment getLocalGraphicsEnvironment()
{
- if (env == null)
- env = new XGraphicsEnvironment();
- return env;
+ return new XGraphicsEnvironment();
}
/**
@@ -176,15 +180,20 @@ public class XToolkit
public ClasspathFontPeer getClasspathFontPeer(String name, Map attrs)
{
String canonical = XFontPeer.encodeFont(name, attrs);
- XFontPeer font;
+ ClasspathFontPeer font;
if (!fontCache.containsKey(canonical))
{
- font = new XFontPeer(name, attrs);
+ String graphics2d =
+ SystemProperties.getProperty("gnu.xawt.graphics2d");
+ if (graphics2d != null && graphics2d.equals("gl"))
+ font = new XFontPeer2(name, attrs);
+ else
+ font = new XFontPeer(name, attrs);
fontCache.put(canonical, font);
}
else
{
- font = (XFontPeer) fontCache.get(canonical);
+ font = (ClasspathFontPeer) fontCache.get(canonical);
}
return font;
}
@@ -282,8 +291,7 @@ public class XToolkit
protected DialogPeer createDialog(Dialog target)
{
- // TODO: Implement this.
- throw new UnsupportedOperationException("Not yet implemented.");
+ return new XDialogPeer(target);
}
protected MenuBarPeer createMenuBar(MenuBar target)
@@ -361,7 +369,7 @@ public class XToolkit
public FontMetrics getFontMetrics(Font name)
{
- XFontPeer peer = (XFontPeer) name.getPeer();
+ ClasspathFontPeer peer = (ClasspathFontPeer) name.getPeer();
return peer.getFontMetrics(name);
}
@@ -459,16 +467,7 @@ public class XToolkit
Image image;
try
{
- BufferedImage buffered = ImageIO.read(url);
- if (buffered != null)
- {
- ImageConverter conv = new ImageConverter();
- ImageProducer source = buffered.getSource();
- source.startProduction(conv);
- return conv.getXImage();
- }
- else return createErrorImage();
-
+ image = createImage(url.openStream());
}
catch (IOException ex)
{
@@ -504,14 +503,48 @@ public class XToolkit
public Image createImage(ImageProducer producer)
{
- // TODO: Implement this.
- throw new UnsupportedOperationException("Not yet implemented.");
+ ImageConverter conv = new ImageConverter();
+ producer.startProduction(conv);
+ Image image = conv.getXImage();
+ return image;
}
public Image createImage(byte[] data, int offset, int len)
{
- // TODO: Implement this.
- throw new UnsupportedOperationException("Not yet implemented.");
+ Image image;
+ try
+ {
+ ByteArrayInputStream i = new ByteArrayInputStream(data, offset, len);
+ image = createImage(i);
+ }
+ catch (IOException ex)
+ {
+ image = createErrorImage();
+ }
+ return image;
+ }
+
+ private Image createImage(InputStream i)
+ throws IOException
+ {
+ Image image;
+ BufferedImage buffered = ImageIO.read(i);
+ // If the bufferedimage is opaque, then we can copy it over to an
+ // X Pixmap for faster drawing.
+ if (buffered != null && buffered.getTransparency() == Transparency.OPAQUE)
+ {
+ ImageProducer source = buffered.getSource();
+ image = createImage(source);
+ }
+ else if (buffered != null)
+ {
+ image = buffered;
+ }
+ else
+ {
+ image = createErrorImage();
+ }
+ return image;
}
public PrintJob getPrintJob(Frame frame, String title, Properties props)
diff --git a/gnu/java/awt/peer/x/XWindowPeer.java b/gnu/java/awt/peer/x/XWindowPeer.java
index f4815ce7f..28cc5a5ed 100644
--- a/gnu/java/awt/peer/x/XWindowPeer.java
+++ b/gnu/java/awt/peer/x/XWindowPeer.java
@@ -85,7 +85,6 @@ public class XWindowPeer
XWindowPeer(java.awt.Window window)
{
super(window);
- System.err.println("new XWindowPeer");
XGraphicsDevice dev = XToolkit.getDefaultDevice();
// TODO: Maybe initialize lazily in show().
diff --git a/gnu/java/awt/peer/x/fonts.properties b/gnu/java/awt/peer/x/fonts.properties
deleted file mode 100644
index 2c8755ceb..000000000
--- a/gnu/java/awt/peer/x/fonts.properties
+++ /dev/null
@@ -1,25 +0,0 @@
-
-serif.plain=-adobe-times-medium-r-normal--%d-*-*-*-p-*-iso8859-1
-serif.bold=-adobe-times-bold-r-normal--%d-*-*-*-p-*-iso8859-1
-serif.italic=-adobe-times-medium-o-normal--%d-*-*-*-p-*-iso8859-1
-serif.bolditalic=-adobe-times-bold-o-normal--%d-*-*-*-p-*-iso8859-1
-
-sansserif.plain=-adobe-helvetica-medium-r-normal--%d-*-*-*-p-*-iso8859-1
-sansserif.bold=-adobe-helvetica-bold-r-normal--%d-*-*-*-p-*-iso8859-1
-sansserif.italic=-adobe-helvetica-medium-o-normal--%d-*-*-*-p-*-iso8859-1
-sansserif.bolditalic=-adobe-helvetica-bold-o-normal--%d-*-*-*-p-*-iso8859-1
-
-monospaced.plain=-adobe-courier-medium-r-normal--%d-*-*-*-p-*-iso8859-1
-monospaced.bold=-adobe-courier-bold-r-normal--%d-*-*-*-p-*-iso8859-1
-monospaced.italic=-adobe-courier-medium-o-normal--%d-*-*-*-p-*-iso8859-1
-monospaced.bolditalic=-adobe-courier-bold-o-normal--%d-*-*-*-p-*-iso8859-1
-
-dialog.plain=-adobe-helvetica-medium-r-normal--%d-*-*-*-p-*-iso8859-1
-dialog.bold=-adobe-helvetica-bold-r-normal--%d-*-*-*-p-*-iso8859-1
-dialog.italic=-adobe-helvetica-medium-o-normal--%d-*-*-*-p-*-iso8859-1
-dialog.bolditalic=-adobe-helvetica-bold-o-normal--%d-*-*-*-p-*-iso8859-1
-
-dialoginput.plain=-adobe-helvetica-medium-r-normal--%d-*-*-*-p-*-iso8859-1
-dialoginput.bold=-adobe-helvetica-bold-r-normal--%d-*-*-*-p-*-iso8859-1
-dialoginput.italic=-adobe-helvetica-medium-o-normal--%d-*-*-*-p-*-iso8859-1
-dialoginput.bolditalic=-adobe-helvetica-bold-o-normal--%d-*-*-*-p-*-iso8859-1
diff --git a/gnu/java/lang/management/BeanImpl.java b/gnu/java/lang/management/BeanImpl.java
index 1845d7abc..529ee5896 100644
--- a/gnu/java/lang/management/BeanImpl.java
+++ b/gnu/java/lang/management/BeanImpl.java
@@ -39,6 +39,50 @@ package gnu.java.lang.management;
import java.lang.management.ManagementPermission;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.TypeVariable;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.AttributeNotFoundException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.MBeanInfo;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ReflectionException;
+import javax.management.StandardMBean;
+
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenMBeanAttributeInfo;
+import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
+import javax.management.openmbean.OpenMBeanConstructorInfo;
+import javax.management.openmbean.OpenMBeanConstructorInfoSupport;
+import javax.management.openmbean.OpenMBeanInfo;
+import javax.management.openmbean.OpenMBeanInfoSupport;
+import javax.management.openmbean.OpenMBeanOperationInfo;
+import javax.management.openmbean.OpenMBeanOperationInfoSupport;
+import javax.management.openmbean.OpenMBeanParameterInfo;
+import javax.management.openmbean.OpenMBeanParameterInfoSupport;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
/**
* A common superclass for bean implementations.
*
@@ -46,8 +90,94 @@ import java.lang.management.ManagementPermission;
* @since 1.5
*/
public class BeanImpl
+ extends StandardMBean
{
+ /**
+ * Cached open bean information.
+ */
+ private OpenMBeanInfo openInfo;
+
+ /**
+ * Constructs a new <code>BeanImpl</code>.
+ *
+ * @param iface the bean interface being implemented.
+ * @throws NotCompliantMBeanException if this class doesn't implement
+ * the interface or a method appears
+ * in the interface that doesn't comply
+ * with the naming conventions.
+ */
+ protected BeanImpl(Class iface)
+ throws NotCompliantMBeanException
+ {
+ super(iface);
+ }
+
+ protected void cacheMBeanInfo(MBeanInfo info)
+ {
+ if (info == null)
+ return;
+ try
+ {
+ MBeanAttributeInfo[] oldA = info.getAttributes();
+ OpenMBeanAttributeInfo[] attribs =
+ new OpenMBeanAttributeInfoSupport[oldA.length];
+ for (int a = 0; a < oldA.length; ++a)
+ {
+ OpenMBeanParameterInfo param = translate(oldA[a].getType());
+ if (param.getMinValue() == null)
+ {
+ Object[] lv;
+ if (param.getLegalValues() == null)
+ lv = null;
+ else
+ lv = param.getLegalValues().toArray();
+ attribs[a] = new OpenMBeanAttributeInfoSupport(oldA[a].getName(),
+ oldA[a].getDescription(),
+ param.getOpenType(),
+ oldA[a].isReadable(),
+ oldA[a].isWritable(),
+ oldA[a].isIs(),
+ param.getDefaultValue(),
+ lv);
+ }
+ else
+ attribs[a] = new OpenMBeanAttributeInfoSupport(oldA[a].getName(),
+ oldA[a].getDescription(),
+ param.getOpenType(),
+ oldA[a].isReadable(),
+ oldA[a].isWritable(),
+ oldA[a].isIs(),
+ param.getDefaultValue(),
+ param.getMinValue(),
+ param.getMaxValue());
+ }
+ MBeanConstructorInfo[] oldC = info.getConstructors();
+ OpenMBeanConstructorInfo[] cons = new OpenMBeanConstructorInfoSupport[oldC.length];
+ for (int a = 0; a < oldC.length; ++a)
+ cons[a] =
+ new OpenMBeanConstructorInfoSupport(oldC[a].getName(),
+ oldC[a].getDescription(),
+ translateSignature(oldC[a].getSignature()));
+ MBeanOperationInfo[] oldO = info.getOperations();
+ OpenMBeanOperationInfo[] ops = new OpenMBeanOperationInfoSupport[oldO.length];
+ for (int a = 0; a < oldO.length; ++a)
+ ops[a] =
+ new OpenMBeanOperationInfoSupport(oldO[a].getName(),
+ oldO[a].getDescription(),
+ translateSignature(oldO[a].getSignature()),
+ translate(oldO[a].getReturnType()).getOpenType(),
+ oldO[a].getImpact());
+ openInfo = new OpenMBeanInfoSupport(info.getClassName(), info.getDescription(),
+ attribs, cons, ops, info.getNotifications());
+ }
+ catch (OpenDataException e)
+ {
+ throw (InternalError) (new InternalError("A problem occurred creating the open type " +
+ "descriptors.").initCause(e));
+ }
+ }
+
protected void checkMonitorPermissions()
{
SecurityManager sm = System.getSecurityManager();
@@ -62,4 +192,335 @@ public class BeanImpl
sm.checkPermission(new ManagementPermission("control"));
}
+ public Object getAttribute(String attribute)
+ throws AttributeNotFoundException, MBeanException,
+ ReflectionException
+ {
+ Object value = super.getAttribute(attribute);
+ if (value instanceof Enum)
+ return ((Enum) value).name();
+ Class vClass = value.getClass();
+ if (vClass.isArray())
+ return value;
+ String cName = vClass.getName();
+ String[] allowedTypes = OpenType.ALLOWED_CLASSNAMES;
+ for (int a = 0; a < allowedTypes.length; ++a)
+ if (cName.equals(allowedTypes[a]))
+ return value;
+ if (value instanceof List)
+ {
+ List l = (List) value;
+ Class e = null;
+ TypeVariable[] vars = vClass.getTypeParameters();
+ for (int a = 0; a < vars.length; ++a)
+ if (vars[a].getName().equals("E"))
+ e = (Class) vars[a].getGenericDeclaration();
+ if (e == null)
+ e = Object.class;
+ Object[] array = (Object[]) Array.newInstance(e, l.size());
+ return l.toArray(array);
+ }
+ OpenMBeanInfo info = (OpenMBeanInfo) getMBeanInfo();
+ OpenMBeanAttributeInfo[] attribs =
+ (OpenMBeanAttributeInfo[]) info.getAttributes();
+ OpenType type = null;
+ for (int a = 0; a < attribs.length; ++a)
+ if (attribs[a].getName().equals("attribute"))
+ type = attribs[a].getOpenType();
+ if (value instanceof Map)
+ {
+ TabularType ttype = (TabularType) type;
+ TabularData data = new TabularDataSupport(ttype);
+ Iterator it = ((Map) value).entrySet().iterator();
+ while (it.hasNext())
+ {
+ Map.Entry entry = (Map.Entry) it.next();
+ try
+ {
+ data.put(new CompositeDataSupport(ttype.getRowType(),
+ new String[] {
+ "key",
+ "value"
+ },
+ new Object[] {
+ entry.getKey(),
+ entry.getValue()
+ }));
+ }
+ catch (OpenDataException e)
+ {
+ throw (InternalError) (new InternalError("A problem occurred " +
+ "converting the map " +
+ "to a composite data " +
+ "structure.").initCause(e));
+ }
+ }
+ return data;
+ }
+ CompositeType cType = (CompositeType) type;
+ Set names = cType.keySet();
+ Iterator it = names.iterator();
+ List values = new ArrayList(names.size());
+ while (it.hasNext())
+ {
+ String field = (String) it.next();
+ Method getter = null;
+ try
+ {
+ getter = vClass.getMethod("get" + field, null);
+ }
+ catch (NoSuchMethodException e)
+ {
+ /* Ignored; the type tells us it's there. */
+ }
+ try
+ {
+ values.add(getter.invoke(value, null));
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new ReflectionException(e, "Failed to retrieve " + field);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ReflectionException(e, "Failed to retrieve " + field);
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new MBeanException((Exception) e.getCause(),
+ "The getter of " + field +
+ " threw an exception");
+ }
+ }
+ try
+ {
+ return new CompositeDataSupport(cType,
+ (String[])
+ names.toArray(new String[names.size()]),
+ values.toArray());
+ }
+ catch (OpenDataException e)
+ {
+ throw (InternalError) (new InternalError("A problem occurred " +
+ "converting the value " +
+ "to a composite data " +
+ "structure.").initCause(e));
+ }
+ }
+
+ protected MBeanInfo getCachedMBeanInfo()
+ {
+ return (MBeanInfo) openInfo;
+ }
+
+ public MBeanInfo getMBeanInfo()
+ {
+ super.getMBeanInfo();
+ return getCachedMBeanInfo();
+ }
+
+ private OpenType getTypeFromClass(Class c)
+ throws OpenDataException
+ {
+ return translate(c.getName()).getOpenType();
+ }
+
+ private OpenMBeanParameterInfo[] translateSignature(MBeanParameterInfo[] oldS)
+ throws OpenDataException
+ {
+ OpenMBeanParameterInfo[] sig = new OpenMBeanParameterInfoSupport[oldS.length];
+ for (int a = 0; a < oldS.length; ++a)
+ {
+ OpenMBeanParameterInfo param = translate(oldS[a].getType());
+ if (param.getMinValue() == null)
+ {
+ Object[] lv;
+ if (param.getLegalValues() == null)
+ lv = null;
+ else
+ lv = param.getLegalValues().toArray();
+ sig[a] = new OpenMBeanParameterInfoSupport(oldS[a].getName(),
+ oldS[a].getDescription(),
+ param.getOpenType(),
+ param.getDefaultValue(),
+ lv);
+ }
+ else
+ sig[a] = new OpenMBeanParameterInfoSupport(oldS[a].getName(),
+ oldS[a].getDescription(),
+ param.getOpenType(),
+ param.getDefaultValue(),
+ param.getMinValue(),
+ param.getMaxValue());
+ }
+ return sig;
+ }
+
+ private OpenMBeanParameterInfo translate(String type)
+ throws OpenDataException
+ {
+ if (type.equals("boolean") || type.equals(Boolean.class.getName()))
+ return new OpenMBeanParameterInfoSupport("TransParam",
+ "Translated parameter",
+ SimpleType.BOOLEAN,
+ null,
+ new Object[] {
+ Boolean.TRUE,
+ Boolean.FALSE
+ });
+ if (type.equals("byte") || type.equals(Byte.class.getName()))
+ return new OpenMBeanParameterInfoSupport("TransParam",
+ "Translated parameter",
+ SimpleType.BYTE,
+ null,
+ Byte.valueOf(Byte.MIN_VALUE),
+ Byte.valueOf(Byte.MAX_VALUE));
+ if (type.equals("char") || type.equals(Character.class.getName()))
+ return new OpenMBeanParameterInfoSupport("TransParam",
+ "Translated parameter",
+ SimpleType.CHARACTER,
+ null,
+ Character.valueOf(Character.MIN_VALUE),
+ Character.valueOf(Character.MAX_VALUE));
+ if (type.equals("double") || type.equals(Double.class.getName()))
+ return new OpenMBeanParameterInfoSupport("TransParam",
+ "Translated parameter",
+ SimpleType.DOUBLE,
+ null,
+ Double.valueOf(Double.MIN_VALUE),
+ Double.valueOf(Double.MAX_VALUE));
+ if (type.equals("float") || type.equals(Float.class.getName()))
+ return new OpenMBeanParameterInfoSupport("TransParam",
+ "Translated parameter",
+ SimpleType.FLOAT,
+ null,
+ Float.valueOf(Float.MIN_VALUE),
+ Float.valueOf(Float.MAX_VALUE));
+ if (type.equals("int") || type.equals(Integer.class.getName()))
+ return new OpenMBeanParameterInfoSupport("TransParam",
+ "Translated parameter",
+ SimpleType.INTEGER,
+ null,
+ Integer.valueOf(Integer.MIN_VALUE),
+ Integer.valueOf(Integer.MAX_VALUE));
+ if (type.equals("long") || type.equals(Long.class.getName()))
+ return new OpenMBeanParameterInfoSupport("TransParam",
+ "Translated parameter",
+ SimpleType.LONG,
+ null,
+ Long.valueOf(Long.MIN_VALUE),
+ Long.valueOf(Long.MAX_VALUE));
+ if (type.equals("short") || type.equals(Short.class.getName()))
+ return new OpenMBeanParameterInfoSupport("TransParam",
+ "Translated parameter",
+ SimpleType.SHORT,
+ null,
+ Short.valueOf(Short.MIN_VALUE),
+ Short.valueOf(Short.MAX_VALUE));
+ if (type.equals(String.class.getName()))
+ return new OpenMBeanParameterInfoSupport("TransParam",
+ "Translated parameter",
+ SimpleType.STRING);
+ if (type.equals("void"))
+ return new OpenMBeanParameterInfoSupport("TransParam",
+ "Translated parameter",
+ SimpleType.VOID);
+ Class c;
+ try
+ {
+ c = Class.forName(type);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new InternalError("The class for a type used in a management bean " +
+ "could not be loaded.");
+ }
+ if (c.isEnum())
+ {
+ Object[] values = c.getEnumConstants();
+ String[] names = new String[values.length];
+ for (int a = 0; a < values.length; ++a)
+ names[a] = values[a].toString();
+ return new OpenMBeanParameterInfoSupport("TransParam",
+ "Translated parameter",
+ SimpleType.STRING,
+ null,
+ (Object[]) names);
+ }
+ try
+ {
+ c.getMethod("from", new Class[] { CompositeData.class });
+ Method[] methods = c.getMethods();
+ List names = new ArrayList();
+ List types = new ArrayList();
+ for (int a = 0; a < methods.length; ++a)
+ {
+ String name = methods[a].getName();
+ if (name.startsWith("get"))
+ {
+ names.add(name.substring(3));
+ types.add(getTypeFromClass(methods[a].getReturnType()));
+ }
+ }
+ String[] fields = (String[]) names.toArray();
+ CompositeType ctype = new CompositeType(c.getName(), c.getName(),
+ fields, fields,
+ (OpenType[]) types.toArray());
+ return new OpenMBeanParameterInfoSupport("TransParam",
+ "Translated parameter",
+ ctype);
+ }
+ catch (NoSuchMethodException e)
+ {
+ /* Ignored; we expect this if this isn't a from(CompositeData) class */
+ }
+ if (Map.class.isAssignableFrom(c))
+ {
+ OpenType k = SimpleType.VOID;
+ OpenType v = SimpleType.VOID;
+ TypeVariable[] vars = c.getTypeParameters();
+ for (int a = 0; a < vars.length; ++a)
+ {
+ if (vars[a].getName().equals("K"))
+ k = getTypeFromClass((Class) vars[a].getGenericDeclaration());
+ if (vars[a].getName().equals("V"))
+ v = getTypeFromClass((Class) vars[a].getGenericDeclaration());
+ }
+ CompositeType ctype = new CompositeType(Map.class.getName(), Map.class.getName(),
+ new String[] { "key", "value" },
+ new String[] { "Map key", "Map value"},
+ new OpenType[] { k, v});
+ TabularType ttype = new TabularType(c.getName(), c.getName(), ctype,
+ new String[] { "key" });
+ return new OpenMBeanParameterInfoSupport("TransParam",
+ "Translated parameter",
+ ttype);
+ }
+ if (List.class.isAssignableFrom(c))
+ {
+ OpenType e = SimpleType.VOID;
+ TypeVariable[] vars = c.getTypeParameters();
+ for (int a = 0; a < vars.length; ++a)
+ {
+ if (vars[a].getName().equals("E"))
+ e = getTypeFromClass((Class) vars[a].getGenericDeclaration());
+ }
+ return new OpenMBeanParameterInfoSupport("TransParam",
+ "Translated parameter",
+ new ArrayType(1, e)
+ );
+ }
+ if (c.isArray())
+ {
+ int depth;
+ for (depth = 0; c.getName().charAt(depth) == '['; ++depth);
+ OpenType ot = getTypeFromClass(c.getComponentType());
+ return new OpenMBeanParameterInfoSupport("TransParam",
+ "Translated parameter",
+ new ArrayType(depth, ot)
+ );
+ }
+ throw new InternalError("The type used does not have an open type translation.");
+ }
+
}
diff --git a/gnu/java/lang/management/ClassLoadingMXBeanImpl.java b/gnu/java/lang/management/ClassLoadingMXBeanImpl.java
index d93ccf2c3..92e68ae76 100644
--- a/gnu/java/lang/management/ClassLoadingMXBeanImpl.java
+++ b/gnu/java/lang/management/ClassLoadingMXBeanImpl.java
@@ -39,6 +39,8 @@ package gnu.java.lang.management;
import java.lang.management.ClassLoadingMXBean;
+import javax.management.NotCompliantMBeanException;
+
/**
* Provides access to information about the class loading
* behaviour of the current invocation of the virtual
@@ -53,6 +55,20 @@ public final class ClassLoadingMXBeanImpl
implements ClassLoadingMXBean
{
+ /**
+ * Constructs a new <code>ClassLoadingMXBeanImpl</code>.
+ *
+ * @throws NotCompliantMBeanException if this class doesn't implement
+ * the interface or a method appears
+ * in the interface that doesn't comply
+ * with the naming conventions.
+ */
+ public ClassLoadingMXBeanImpl()
+ throws NotCompliantMBeanException
+ {
+ super(ClassLoadingMXBean.class);
+ }
+
public int getLoadedClassCount()
{
return VMClassLoadingMXBeanImpl.getLoadedClassCount();
diff --git a/gnu/java/lang/management/CompilationMXBeanImpl.java b/gnu/java/lang/management/CompilationMXBeanImpl.java
index 044150fae..b3ad898b5 100644
--- a/gnu/java/lang/management/CompilationMXBeanImpl.java
+++ b/gnu/java/lang/management/CompilationMXBeanImpl.java
@@ -41,6 +41,8 @@ import gnu.classpath.SystemProperties;
import java.lang.management.CompilationMXBean;
+import javax.management.NotCompliantMBeanException;
+
/**
* Provides access to information about the JIT
* compiler of the virtual machine, if one exists.
@@ -67,6 +69,20 @@ public final class CompilationMXBeanImpl
private static final String COMPILATION_TIME_SUPPORT =
"gnu.java.lang.management.CompilationTimeSupport";
+ /**
+ * Constructs a new <code>CompilationMXBeanImpl</code>.
+ *
+ * @throws NotCompliantMBeanException if this class doesn't implement
+ * the interface or a method appears
+ * in the interface that doesn't comply
+ * with the naming conventions.
+ */
+ public CompilationMXBeanImpl()
+ throws NotCompliantMBeanException
+ {
+ super(CompilationMXBean.class);
+ }
+
public String getName()
{
return SystemProperties.getProperty(COMPILER_NAME);
diff --git a/gnu/java/lang/management/GarbageCollectorMXBeanImpl.java b/gnu/java/lang/management/GarbageCollectorMXBeanImpl.java
index 19db8df1b..b752e6b86 100644
--- a/gnu/java/lang/management/GarbageCollectorMXBeanImpl.java
+++ b/gnu/java/lang/management/GarbageCollectorMXBeanImpl.java
@@ -39,6 +39,8 @@ package gnu.java.lang.management;
import java.lang.management.GarbageCollectorMXBean;
+import javax.management.NotCompliantMBeanException;
+
/**
* Provides access to information about one of the garbage
* collectors used by the current invocation of the
@@ -58,10 +60,15 @@ public final class GarbageCollectorMXBeanImpl
* Constructs a new <code>GarbageCollectorMXBeanImpl</code>.
*
* @param name the name of the garbage collector this bean represents.
+ * @throws NotCompliantMBeanException if this class doesn't implement
+ * the interface or a method appears
+ * in the interface that doesn't comply
+ * with the naming conventions.
*/
public GarbageCollectorMXBeanImpl(String name)
+ throws NotCompliantMBeanException
{
- super(name);
+ super(name, GarbageCollectorMXBean.class);
}
public long getCollectionCount()
diff --git a/gnu/java/lang/management/MemoryMXBeanImpl.java b/gnu/java/lang/management/MemoryMXBeanImpl.java
index 614ae18b8..064e19a19 100644
--- a/gnu/java/lang/management/MemoryMXBeanImpl.java
+++ b/gnu/java/lang/management/MemoryMXBeanImpl.java
@@ -38,8 +38,28 @@ exception statement from your version. */
package gnu.java.lang.management;
import java.lang.management.MemoryMXBean;
+import java.lang.management.MemoryNotificationInfo;
import java.lang.management.MemoryUsage;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanNotificationInfo;
+import javax.management.NotCompliantMBeanException;
+import javax.management.Notification;
+import javax.management.NotificationEmitter;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+
/**
* Provides access to information about the memory
* management of the current invocation of the virtual
@@ -51,9 +71,72 @@ import java.lang.management.MemoryUsage;
*/
public final class MemoryMXBeanImpl
extends BeanImpl
- implements MemoryMXBean
+ implements MemoryMXBean, NotificationEmitter
{
+ private List listeners;
+
+ private long notificationCount;
+
+ public static CompositeType notifType;
+
+ public static CompositeType usageType;
+
+ static
+ {
+ try
+ {
+ CompositeType usageType =
+ new CompositeType(MemoryUsage.class.getName(),
+ "Describes the usage levels of a pool",
+ new String[] { "init", "used",
+ "committed", "max"
+ },
+ new String[] { "Initial level",
+ "Used level",
+ "Committed level",
+ "Maximum level"
+ },
+ new OpenType[] {
+ SimpleType.LONG, SimpleType.LONG,
+ SimpleType.LONG, SimpleType.LONG
+ });
+ CompositeType notifType =
+ new CompositeType(MemoryNotificationInfo.class.getName(),
+ "Provides the notification info on memory usage",
+ new String[] { "poolName", "usage", "count" },
+ new String[] { "Name of the memory pool",
+ "Usage level of the memory pool",
+ "Number of times the threshold " +
+ "has been crossed"
+ },
+ new OpenType[] {
+ SimpleType.STRING, usageType, SimpleType.LONG
+ });
+ }
+ catch (OpenDataException e)
+ {
+ throw new IllegalStateException("Something went wrong in creating " +
+ "the composite data types.", e);
+ }
+ }
+
+ /**
+ * Constructs a new <code>MemoryMXBeanImpl</code>.
+ *
+ * @throws NotCompliantMBeanException if this class doesn't implement
+ * the interface or a method appears
+ * in the interface that doesn't comply
+ * with the naming conventions.
+ */
+ public MemoryMXBeanImpl()
+ throws NotCompliantMBeanException
+ {
+ super(MemoryMXBean.class);
+ listeners = new ArrayList();
+ notificationCount = 0;
+ }
+
public void gc()
{
System.gc();
@@ -85,4 +168,155 @@ public final class MemoryMXBeanImpl
VMMemoryMXBeanImpl.setVerbose(verbose);
}
+ private class ListenerData
+ {
+ private NotificationListener listener;
+ private NotificationFilter filter;
+ private Object passback;
+
+ public ListenerData(NotificationListener listener,
+ NotificationFilter filter, Object passback)
+ {
+ this.listener = listener;
+ this.filter = filter;
+ this.passback = passback;
+ }
+
+ public NotificationListener getListener()
+ {
+ return listener;
+ }
+
+ public NotificationFilter getFilter()
+ {
+ return filter;
+ }
+
+ public Object getPassback()
+ {
+ return passback;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof ListenerData)
+ {
+ ListenerData data = (ListenerData) obj;
+ return (data.getListener() == listener &&
+ data.getFilter() == filter &&
+ data.getPassback() == passback);
+ }
+ return false;
+ }
+
+ }
+
+ public void addNotificationListener(NotificationListener listener,
+ NotificationFilter filter,
+ Object passback)
+ {
+ if (listener == null)
+ throw new IllegalArgumentException("Null listener added to bean.");
+ listeners.add(new ListenerData(listener, filter, passback));
+ }
+
+ public MBeanNotificationInfo[] getNotificationInfo()
+ {
+ return new MBeanNotificationInfo[]
+ {
+ new MBeanNotificationInfo(new String[]
+ {
+ MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED,
+ MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED
+ },
+ Notification.class.getName(),
+ "Memory Usage Notifications")
+ };
+ }
+
+ public void removeNotificationListener(NotificationListener listener)
+ throws ListenerNotFoundException
+ {
+ Iterator it = listeners.iterator();
+ boolean foundOne = false;
+ while (it.hasNext())
+ {
+ ListenerData data = (ListenerData) it.next();
+ if (data.getListener() == listener)
+ {
+ it.remove();
+ foundOne = true;
+ }
+ }
+ if (!foundOne)
+ throw new ListenerNotFoundException("The specified listener, " + listener +
+ "is not registered with this bean.");
+ }
+
+ public void removeNotificationListener(NotificationListener listener,
+ NotificationFilter filter,
+ Object passback)
+ throws ListenerNotFoundException
+ {
+ if (!(listeners.remove(new ListenerData(listener, filter, passback))))
+ {
+ throw new ListenerNotFoundException("The specified listener, " + listener +
+ " with filter " + filter +
+ "and passback " + passback +
+ ", is not registered with this bean.");
+ }
+ }
+
+ void fireNotification(String type, String poolName, long init, long used,
+ long committed, long max, long count)
+ {
+ Notification notif = new Notification(type, this, notificationCount);
+ MemoryUsage usage = new MemoryUsage(init, used, committed, max);
+ CompositeData data;
+ try
+ {
+ data = new CompositeDataSupport(notifType,
+ new String[] {
+ "poolName", "usage", "count"
+ },
+ new Object[] {
+ poolName, usage, Long.valueOf(count)
+ });
+ }
+ catch (OpenDataException e)
+ {
+ throw new IllegalStateException("Something went wrong in creating " +
+ "the composite data instance.", e);
+ }
+ notif.setUserData(data);
+ Iterator it = listeners.iterator();
+ while (it.hasNext())
+ {
+ ListenerData ldata = (ListenerData) it.next();
+ NotificationFilter filter = ldata.getFilter();
+ if (filter == null || filter.isNotificationEnabled(notif))
+ ldata.getListener().handleNotification(notif, ldata.getPassback());
+ }
+ ++notificationCount;
+ }
+
+ void fireThresholdExceededNotification(String poolName, long init,
+ long used, long committed,
+ long max, long count)
+ {
+ fireNotification(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED,
+ poolName, init, used, committed, max, count);
+ }
+
+ void fireCollectionThresholdExceededNotification(String poolName,
+ long init,
+ long used,
+ long committed,
+ long max,
+ long count)
+ {
+ fireNotification(MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED,
+ poolName, init, used, committed, max, count);
+ }
+
}
diff --git a/gnu/java/lang/management/MemoryManagerMXBeanImpl.java b/gnu/java/lang/management/MemoryManagerMXBeanImpl.java
index 2c6d4472a..5766af9cc 100644
--- a/gnu/java/lang/management/MemoryManagerMXBeanImpl.java
+++ b/gnu/java/lang/management/MemoryManagerMXBeanImpl.java
@@ -39,6 +39,8 @@ package gnu.java.lang.management;
import java.lang.management.MemoryManagerMXBean;
+import javax.management.NotCompliantMBeanException;
+
/**
* Provides access to information about one of the memory
* managers used by the current invocation of the
@@ -63,9 +65,32 @@ public class MemoryManagerMXBeanImpl
* Constructs a new <code>MemoryManagerMXBeanImpl</code>.
*
* @param name the name of the manager this bean represents.
+ * @throws NotCompliantMBeanException if this class doesn't implement
+ * the interface or a method appears
+ * in the interface that doesn't comply
+ * with the naming conventions.
*/
public MemoryManagerMXBeanImpl(String name)
+ throws NotCompliantMBeanException
+ {
+ this(name, MemoryManagerMXBean.class);
+ }
+
+ /**
+ * Constructs a new <code>MemoryManagerMXBeanImpl</code>
+ * implementing the specified bean interface.
+ *
+ * @param name the name of the manager this bean represents.
+ * @param iface the bean interface being implemented.
+ * @throws NotCompliantMBeanException if this class doesn't implement
+ * the interface or a method appears
+ * in the interface that doesn't comply
+ * with the naming conventions.
+ */
+ protected MemoryManagerMXBeanImpl(String name, Class iface)
+ throws NotCompliantMBeanException
{
+ super(iface);
this.name = name;
}
diff --git a/gnu/java/lang/management/MemoryPoolMXBeanImpl.java b/gnu/java/lang/management/MemoryPoolMXBeanImpl.java
index af718e3ff..ed4dccd76 100644
--- a/gnu/java/lang/management/MemoryPoolMXBeanImpl.java
+++ b/gnu/java/lang/management/MemoryPoolMXBeanImpl.java
@@ -42,6 +42,8 @@ import gnu.classpath.SystemProperties;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
+import javax.management.NotCompliantMBeanException;
+
/**
* Provides access to information about one of the memory
* resources or pools used by the current invocation of the
@@ -78,9 +80,15 @@ public final class MemoryPoolMXBeanImpl
* Constructs a new <code>MemoryPoolMXBeanImpl</code>.
*
* @param name the name of the pool this bean represents.
+ * @throws NotCompliantMBeanException if this class doesn't implement
+ * the interface or a method appears
+ * in the interface that doesn't comply
+ * with the naming conventions.
*/
public MemoryPoolMXBeanImpl(String name)
+ throws NotCompliantMBeanException
{
+ super(MemoryPoolMXBean.class);
this.name = name;
}
@@ -125,6 +133,11 @@ public final class MemoryPoolMXBeanImpl
return null;
}
+ public String getType()
+ {
+ return VMMemoryPoolMXBeanImpl.getType(name);
+ }
+
public MemoryUsage getUsage()
{
if (isValid())
diff --git a/gnu/java/lang/management/OperatingSystemMXBeanImpl.java b/gnu/java/lang/management/OperatingSystemMXBeanImpl.java
index 7e76c8cd1..9eefc0d9d 100644
--- a/gnu/java/lang/management/OperatingSystemMXBeanImpl.java
+++ b/gnu/java/lang/management/OperatingSystemMXBeanImpl.java
@@ -39,6 +39,8 @@ package gnu.java.lang.management;
import java.lang.management.OperatingSystemMXBean;
+import javax.management.NotCompliantMBeanException;
+
/**
* Provides access to information about the underlying operating
* system.
@@ -50,7 +52,21 @@ public final class OperatingSystemMXBeanImpl
extends BeanImpl
implements OperatingSystemMXBean
{
-
+
+ /**
+ * Constructs a new <code>OperatingSystemMXBeanImpl</code>.
+ *
+ * @throws NotCompliantMBeanException if this class doesn't implement
+ * the interface or a method appears
+ * in the interface that doesn't comply
+ * with the naming conventions.
+ */
+ public OperatingSystemMXBeanImpl()
+ throws NotCompliantMBeanException
+ {
+ super(OperatingSystemMXBean.class);
+ }
+
public String getArch()
{
return System.getProperty("os.arch");
diff --git a/gnu/java/lang/management/RuntimeMXBeanImpl.java b/gnu/java/lang/management/RuntimeMXBeanImpl.java
index 2e02cc561..e3ebd162e 100644
--- a/gnu/java/lang/management/RuntimeMXBeanImpl.java
+++ b/gnu/java/lang/management/RuntimeMXBeanImpl.java
@@ -49,6 +49,8 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
+import javax.management.NotCompliantMBeanException;
+
/**
* Provides access to information about the virtual machine.
*
@@ -69,6 +71,20 @@ public final class RuntimeMXBeanImpl
private boolean bootClassPathSupported = true;
+ /**
+ * Constructs a new <code>RuntimeMXBeanImpl</code>.
+ *
+ * @throws NotCompliantMBeanException if this class doesn't implement
+ * the interface or a method appears
+ * in the interface that doesn't comply
+ * with the naming conventions.
+ */
+ public RuntimeMXBeanImpl()
+ throws NotCompliantMBeanException
+ {
+ super(RuntimeMXBean.class);
+ }
+
public String getBootClassPath()
{
checkMonitorPermissions();
diff --git a/gnu/java/lang/management/ThreadMXBeanImpl.java b/gnu/java/lang/management/ThreadMXBeanImpl.java
index f788fd5b3..609b58da7 100644
--- a/gnu/java/lang/management/ThreadMXBeanImpl.java
+++ b/gnu/java/lang/management/ThreadMXBeanImpl.java
@@ -42,6 +42,8 @@ import gnu.classpath.SystemProperties;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
+import javax.management.NotCompliantMBeanException;
+
/**
* Provides access to information about the threads
* of the virtual machine. An instance of this bean is
@@ -96,9 +98,16 @@ public final class ThreadMXBeanImpl
* Default constructor to set up flag states. The
* VM has to specify whether time monitoring is initially
* enabled or not.
+ *
+ * @throws NotCompliantMBeanException if this class doesn't implement
+ * the interface or a method appears
+ * in the interface that doesn't comply
+ * with the naming conventions.
*/
public ThreadMXBeanImpl()
+ throws NotCompliantMBeanException
{
+ super(ThreadMXBean.class);
timeEnabled = Boolean.parseBoolean(SystemProperties.getProperty(TIME_ENABLED));
contentionEnabled = false;
}
diff --git a/gnu/java/net/local/LocalSocketImpl.java b/gnu/java/net/local/LocalSocketImpl.java
index f907e5f46..f43305a80 100644
--- a/gnu/java/net/local/LocalSocketImpl.java
+++ b/gnu/java/net/local/LocalSocketImpl.java
@@ -57,7 +57,8 @@ final class LocalSocketImpl extends SocketImpl
private boolean created;
private InputStream in;
private OutputStream out;
- private int socket_fd;
+ // Package private to avoid synthetic accessor method.
+ int socket_fd;
private LocalSocketAddress local;
private LocalSocketAddress remote;
@@ -104,7 +105,7 @@ final class LocalSocketImpl extends SocketImpl
protected native void create (boolean stream) throws IOException;
protected native void listen (int timeout) throws IOException;
protected native void accept (LocalSocketImpl socket) throws IOException;
- protected native int available () throws IOException;
+ protected native int available (int fd) throws IOException;
protected native void close () throws IOException;
protected native void sendUrgentData (int data) throws IOException;
protected native void shutdownInput () throws IOException;
@@ -113,8 +114,14 @@ final class LocalSocketImpl extends SocketImpl
native void unlink () throws IOException;
native void localBind (LocalSocketAddress addr) throws IOException;
native void localConnect (LocalSocketAddress addr) throws IOException;
- native int read (byte[] buf, int off, int len) throws IOException;
- native void write (byte[] buf, int off, int len) throws IOException;
+ native int read (int fd, byte[] buf, int off, int len) throws IOException;
+ native void write (int fd, byte[] buf, int off, int len) throws IOException;
+
+ protected int available()
+ throws IOException
+ {
+ return available(socket_fd);
+ }
void doCreate () throws IOException
{
@@ -263,7 +270,7 @@ final class LocalSocketImpl extends SocketImpl
public int read (byte[] buf, int off, int len) throws IOException
{
- int ret = impl.read (buf, off, len);
+ int ret = impl.read (socket_fd, buf, off, len);
if (ret == 0)
{
@@ -316,7 +323,7 @@ final class LocalSocketImpl extends SocketImpl
public void write (byte[] buf, int off, int len) throws IOException
{
- impl.write (buf, off, len);
+ impl.write (socket_fd, buf, off, len);
}
}
}
diff --git a/gnu/java/net/protocol/http/Request.java b/gnu/java/net/protocol/http/Request.java
index e15ec4182..cd9d7ea44 100644
--- a/gnu/java/net/protocol/http/Request.java
+++ b/gnu/java/net/protocol/http/Request.java
@@ -419,13 +419,16 @@ public class Request
switch (code)
{
case 100:
+ break;
case 204:
case 205:
case 304:
+ body = createResponseBodyStream(responseHeaders, majorVersion,
+ minorVersion, in, false);
break;
default:
body = createResponseBodyStream(responseHeaders, majorVersion,
- minorVersion, in);
+ minorVersion, in, true);
}
// Construct response
@@ -453,7 +456,8 @@ public class Request
private InputStream createResponseBodyStream(Headers responseHeaders,
int majorVersion,
int minorVersion,
- InputStream in)
+ InputStream in,
+ boolean mayHaveBody)
throws IOException
{
long contentLength = -1;
@@ -466,7 +470,12 @@ public class Request
(majorVersion == 1 && minorVersion == 0);
String transferCoding = responseHeaders.getValue("Transfer-Encoding");
- if ("chunked".equalsIgnoreCase(transferCoding))
+ if ("HEAD".equals(method) || !mayHaveBody)
+ {
+ // Special case no body.
+ in = new LimitedLengthInputStream(in, 0, true, connection, doClose);
+ }
+ else if ("chunked".equalsIgnoreCase(transferCoding))
{
in = new LimitedLengthInputStream(in, -1, false, connection, doClose);
diff --git a/gnu/java/nio/SelectionKeyImpl.java b/gnu/java/nio/SelectionKeyImpl.java
index a1f125e9f..8745377c5 100644
--- a/gnu/java/nio/SelectionKeyImpl.java
+++ b/gnu/java/nio/SelectionKeyImpl.java
@@ -1,5 +1,5 @@
/* SelectionKeyImpl.java --
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -47,8 +47,8 @@ public abstract class SelectionKeyImpl extends AbstractSelectionKey
{
private int readyOps;
private int interestOps;
- private SelectorImpl impl;
- SelectableChannel ch;
+ private final SelectorImpl impl;
+ final SelectableChannel ch;
public SelectionKeyImpl (SelectableChannel ch, SelectorImpl impl)
{
@@ -61,7 +61,7 @@ public abstract class SelectionKeyImpl extends AbstractSelectionKey
return ch;
}
- public int readyOps ()
+ public synchronized int readyOps ()
{
if (!isValid())
throw new CancelledKeyException();
@@ -69,7 +69,7 @@ public abstract class SelectionKeyImpl extends AbstractSelectionKey
return readyOps;
}
- public SelectionKey readyOps (int ops)
+ public synchronized SelectionKey readyOps (int ops)
{
if (!isValid())
throw new CancelledKeyException();
@@ -83,15 +83,21 @@ public abstract class SelectionKeyImpl extends AbstractSelectionKey
if (!isValid())
throw new CancelledKeyException();
- return interestOps;
+ synchronized (impl.selectedKeys())
+ {
+ return interestOps;
+ }
}
public SelectionKey interestOps (int ops)
{
if (!isValid())
throw new CancelledKeyException();
-
- interestOps = ops;
+
+ synchronized (impl.selectedKeys())
+ {
+ interestOps = ops;
+ }
return this;
}
diff --git a/gnu/java/nio/SelectorImpl.java b/gnu/java/nio/SelectorImpl.java
index 7639c9ae3..d0ec48713 100644
--- a/gnu/java/nio/SelectorImpl.java
+++ b/gnu/java/nio/SelectorImpl.java
@@ -1,5 +1,5 @@
/* SelectorImpl.java --
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -387,10 +387,11 @@ public class SelectorImpl extends AbstractSelector
synchronized (keys)
{
keys.add (result);
+
+ result.interestOps (ops);
+ result.attach (att);
}
- result.interestOps (ops);
- result.attach (att);
return result;
}
}
diff --git a/gnu/java/rmi/server/ActivatableServerRef.java b/gnu/java/rmi/server/ActivatableServerRef.java
index 09595ec5f..5b7dadfd2 100644
--- a/gnu/java/rmi/server/ActivatableServerRef.java
+++ b/gnu/java/rmi/server/ActivatableServerRef.java
@@ -178,7 +178,7 @@ public class ActivatableServerRef extends UnicastServerRef
Class cls = aClass;
// where ist the _Stub? (check superclasses also)
- Class expCls = expCls = findStubSkelClass(cls);
+ Class expCls = findStubSkelClass(cls);
if (expCls != null)
{
diff --git a/gnu/java/rmi/server/UnicastServerRef.java b/gnu/java/rmi/server/UnicastServerRef.java
index cd891a1aa..2f7cb9a2d 100644
--- a/gnu/java/rmi/server/UnicastServerRef.java
+++ b/gnu/java/rmi/server/UnicastServerRef.java
@@ -150,7 +150,7 @@ public class UnicastServerRef
Class cls = obj.getClass();
// where ist the _Stub? (check superclasses also)
- Class expCls = expCls = findStubSkelClass(cls);
+ Class expCls = findStubSkelClass(cls);
if (expCls != null)
{
diff --git a/gnu/java/security/Engine.java b/gnu/java/security/Engine.java
index f3be45075..44318af8e 100644
--- a/gnu/java/security/Engine.java
+++ b/gnu/java/security/Engine.java
@@ -42,6 +42,7 @@ import java.lang.reflect.InvocationTargetException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
+import java.util.Enumeration;
/**
* Generic implementation of the getInstance methods in the various
@@ -78,145 +79,170 @@ public final class Engine
/** This class cannot be instantiated. */
private Engine() { }
- // Class method.
- // ------------------------------------------------------------------------
-
/**
- * Get the implementation for <i>algorithm</i> for service
- * <i>service</i> from <i>provider</i>. The service is e.g.
- * "Signature", and the algorithm "DSA".
- *
- * @param service The service name.
+ * Return the implementation for <i>algorithm</i> for service <i>service</i>
+ * from <i>provider</i>. The service is e.g. "Signature", and the algorithm
+ * "DSA".
+ *
+ * @param service The service name.
* @param algorithm The name of the algorithm to get.
- * @param provider The provider to get the implementation from.
- * @return The engine class for the specified algorithm; the object
- * returned is typically a subclass of the SPI class for that
- * service, but callers should check that this is so.
- * @throws NoSuchAlgorithmException If the implementation cannot be
- * found or cannot be instantiated.
- * @throws InvocationTargetException If the SPI class's constructor
- * throws an exception.
- * @throws IllegalArgumentException If any of the three arguments are null.
+ * @param provider The provider to get the implementation from.
+ * @return The engine class for the specified algorithm; the object returned
+ * is typically a subclass of the SPI class for that service, but
+ * callers should check that this is so.
+ * @throws NoSuchAlgorithmException If the implementation cannot be found or
+ * cannot be instantiated.
+ * @throws InvocationTargetException If the SPI class's constructor throws an
+ * exception.
+ * @throws IllegalArgumentException If any of the three arguments is null.
*/
public static Object getInstance(String service, String algorithm,
Provider provider)
- throws InvocationTargetException, NoSuchAlgorithmException
+ throws InvocationTargetException, NoSuchAlgorithmException
{
return getInstance(service, algorithm, provider, NO_ARGS);
}
/**
- * Get the implementation for <i>algorithm</i> for service
- * <i>service</i> from <i>provider</i>, passing <i>initArgs</i> to the
- * SPI class's constructor (which cannot be null; pass a zero-length
- * array if the SPI takes no arguments). The service is e.g.
- * "Signature", and the algorithm "DSA".
- *
- * @param service The service name.
+ * Return the implementation for <i>algorithm</i> for service <i>service</i>
+ * from <i>provider</i>, passing <i>initArgs</i> to the SPI class's
+ * constructor (which cannot be null; pass a zero-length array if the SPI
+ * takes no arguments). The service is e.g. "Signature", and the algorithm
+ * "DSA".
+ *
+ * @param service The service name.
* @param algorithm The name of the algorithm to get.
- * @param provider The provider to get the implementation from.
- * @param initArgs The arguments to pass to the SPI class's
- * constructor (cannot be null).
- * @return The engine class for the specified algorithm; the object
- * returned is typically a subclass of the SPI class for that
- * service, but callers should check that this is so.
- * @throws NoSuchAlgorithmException If the implementation cannot be
- * found or cannot be instantiated.
- * @throws InvocationTargetException If the SPI class's constructor
- * throws an exception.
- * @throws IllegalArgumentException If any of the four arguments are null.
+ * @param provider The provider to get the implementation from.
+ * @param initArgs The arguments to pass to the SPI class's constructor
+ * (cannot be null).
+ * @return The engine class for the specified algorithm; the object returned
+ * is typically a subclass of the SPI class for that service, but
+ * callers should check that this is so.
+ * @throws NoSuchAlgorithmException If the implementation cannot be found or
+ * cannot be instantiated.
+ * @throws InvocationTargetException If the SPI class's constructor throws an
+ * exception.
+ * @throws IllegalArgumentException If any of the four arguments is
+ * <code>null</code> or if either <code>service</code>, or
+ * <code>algorithm</code> is an empty string.
*/
public static Object getInstance(String service, String algorithm,
Provider provider, Object[] initArgs)
- throws InvocationTargetException, NoSuchAlgorithmException
+ throws InvocationTargetException, NoSuchAlgorithmException
{
- if (service != null)
- service = service.trim();
+ if (service == null)
+ throw new IllegalArgumentException("service MUST NOT be null");
+ service = service.trim();
+ if (service.length() == 0)
+ throw new IllegalArgumentException("service MUST NOT be empty");
+ if (algorithm == null)
+ throw new IllegalArgumentException("algorithm MUST NOT be null");
+ algorithm = algorithm.trim();
+ if (algorithm.length() == 0)
+ throw new IllegalArgumentException("algorithm MUST NOT be empty");
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ if (initArgs == null)
+ throw new IllegalArgumentException("Constructor's parameters MUST NOT be null");
- if (algorithm != null)
- algorithm = algorithm.trim();
-
- if (service == null || service.length() == 0
- || algorithm == null || algorithm.length() == 0
- || provider == null || initArgs == null)
- throw new IllegalArgumentException();
-
- // If there is no property "service.algorithm"
- if (provider.getProperty(service + "." + algorithm) == null)
+ Enumeration enumer = provider.propertyNames();
+ String key;
+ String alias;
+ int count = 0;
+ boolean algorithmFound = false;
+ StringBuilder sb = new StringBuilder();
+ while (enumer.hasMoreElements())
{
- // Iterate through aliases, until we find the class name or resolve
- // too many aliases.
- String alias = null;
- int count = 0;
- while ((alias = provider.getProperty(
- ALG_ALIAS + service + "." + algorithm)) != null)
+ key = (String) enumer.nextElement();
+ if (key.equalsIgnoreCase(service + "." + algorithm))
+ {
+ // remove the service portion from the key
+ algorithm = key.substring(service.length() + 1);
+ algorithmFound = true;
+ break;
+ }
+ else if (key.equalsIgnoreCase(ALG_ALIAS + service + "." + algorithm))
{
- if (algorithm.equals(alias)) // Refers to itself!
- break;
- algorithm = alias;
- if (count++ > MAX_ALIASES)
- throw new NoSuchAlgorithmException("too many aliases");
+ alias = (String) provider.getProperty(key);
+ if (! algorithm.equalsIgnoreCase(alias)) // does not refer to itself
+ {
+ algorithm = alias;
+ if (count++ > MAX_ALIASES)
+ {
+ sb.append("Algorithm [").append(algorithm)
+ .append("] of type [").append(service)
+ .append("] from provider [").append(provider)
+ .append("] has too many aliases");
+ throw new NoSuchAlgorithmException(sb.toString());
+ }
+ // need to reset enumeration to now look for the alias
+ enumer = provider.propertyNames();
+ }
}
- if (provider.getProperty(service + "." + algorithm) == null)
- throw new NoSuchAlgorithmException(algorithm);
}
- // Find and instantiate the implementation.
+ if (! algorithmFound)
+ {
+ sb.append("Algorithm [").append(algorithm).append("] of type [")
+ .append(service).append("] from provider [")
+ .append(provider).append("] is not found");
+ throw new NoSuchAlgorithmException(sb.toString());
+ }
+
+ // Find and instantiate the implementation
Class clazz = null;
ClassLoader loader = provider.getClass().getClassLoader();
Constructor constructor = null;
- String error = algorithm;
- Throwable cause;
-
+ String className = provider.getProperty(service + "." + algorithm);
+ sb.append("Class [").append(className).append("] for algorithm [")
+ .append(algorithm).append("] of type [").append(service)
+ .append("] from provider [").append(provider).append("] ");
+ Throwable cause = null;
try
{
if (loader != null)
- clazz = loader.loadClass(provider.getProperty(service+"."+algorithm));
+ clazz = loader.loadClass(className);
else
- clazz = Class.forName(provider.getProperty(service+"."+algorithm));
+ clazz = Class.forName(className);
constructor = getCompatibleConstructor(clazz, initArgs);
return constructor.newInstance(initArgs);
}
- catch (ClassNotFoundException cnfe)
+ catch (ClassNotFoundException x)
{
- error = "class not found: " + algorithm;
- cause = cnfe;
+ sb.append("cannot not be found");
+ cause = x;
}
- catch (IllegalAccessException iae)
+ catch (IllegalAccessException x)
{
- error = "illegal access: " + iae.getMessage();
- cause = iae;
+ sb.append("cannot be accessed");
+ cause = x;
}
- catch (InstantiationException ie)
+ catch (InstantiationException x)
{
- error = "instantiation exception: " + ie.getMessage();
- cause = ie;
+ sb.append("cannot be instantiated");
+ cause = x;
}
- catch (ExceptionInInitializerError eiie)
+ catch (ExceptionInInitializerError x)
{
- error = "exception in initializer: " + eiie.getMessage();
- cause = eiie;
+ sb.append("cannot be initialized");
+ cause = x;
}
- catch (SecurityException se)
+ catch (SecurityException x)
{
- error = "security exception: " + se.getMessage();
- cause = se;
+ sb.append("caused a security violation");
+ cause = x;
}
- catch (NoSuchMethodException nsme)
+ catch (NoSuchMethodException x)
{
- error = "no appropriate constructor found";
- cause = nsme;
+ sb.append("does not have/expose an appropriate constructor");
+ cause = x;
}
- NoSuchAlgorithmException nsae = new NoSuchAlgorithmException(error);
- nsae.initCause(cause);
-
- throw nsae;
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Own methods.
- // ------------------------------------------------------------------------
-
/**
* Find a constructor in the given class that can take the specified
* argument list, allowing any of which to be null.
diff --git a/gnu/java/security/OID.java b/gnu/java/security/OID.java
index 822ca3427..f61cf0fc3 100644
--- a/gnu/java/security/OID.java
+++ b/gnu/java/security/OID.java
@@ -71,6 +71,9 @@ public class OID implements Cloneable, Comparable, java.io.Serializable
// Fields.
// ------------------------------------------------------------------------
+ /* Serial version id for serialization. */
+ static final long serialVersionUID = 5722492029044597779L;
+
/**
* The numeric ID structure.
*/
@@ -229,13 +232,6 @@ public class OID implements Cloneable, Comparable, java.io.Serializable
}
}
- /**
- * Our private constructor.
- */
- private OID()
- {
- }
-
// Instance methods.
// ------------------------------------------------------------------------
@@ -325,10 +321,16 @@ public class OID implements Cloneable, Comparable, java.io.Serializable
*/
public Object clone()
{
- OID oid = new OID();
- oid.components = this.components;
- oid.strRep = this.strRep;
- return oid;
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException cnse)
+ {
+ InternalError ie = new InternalError();
+ ie.initCause(cnse);
+ throw ie;
+ }
}
/* Nice idea, but possibly too expensive for whatever benefit it
diff --git a/gnu/java/security/PolicyFile.java b/gnu/java/security/PolicyFile.java
index 8404eeb98..8da3a7d72 100644
--- a/gnu/java/security/PolicyFile.java
+++ b/gnu/java/security/PolicyFile.java
@@ -37,9 +37,9 @@ exception statement from your version. */
package gnu.java.security;
-import gnu.classpath.SystemProperties;
import gnu.classpath.debug.Component;
import gnu.classpath.debug.SystemLogger;
+import gnu.java.security.action.GetPropertyAction;
import java.io.File;
import java.io.IOException;
@@ -149,15 +149,16 @@ public final class PolicyFile extends Policy
// -------------------------------------------------------------------------
protected static final Logger logger = SystemLogger.SYSTEM;
-
+ // Added to cut redundant AccessController.doPrivileged calls
+ private static GetPropertyAction prop = new GetPropertyAction("file.seperator");
+ private static final String fs = (String) AccessController.doPrivileged(prop);
+
private static final String DEFAULT_POLICY =
- SystemProperties.getProperty("java.home")
- + SystemProperties.getProperty("file.separator") + "lib"
- + SystemProperties.getProperty("file.separator") + "security"
- + SystemProperties.getProperty("file.separator") + "java.policy";
+ (String) AccessController.doPrivileged(prop.setParameters("java.home"))
+ + fs + "lib" + fs + "security" + fs + "java.policy";
private static final String DEFAULT_USER_POLICY =
- SystemProperties.getProperty ("user.home") +
- SystemProperties.getProperty ("file.separator") + ".java.policy";
+ (String) AccessController.doPrivileged(prop.setParameters("user.home")) +
+ fs + ".java.policy";
private final Map cs2pc;
@@ -216,7 +217,7 @@ public final class PolicyFile extends Policy
String allow = Security.getProperty ("policy.allowSystemProperty");
if (allow == null || Boolean.getBoolean (allow))
{
- String s = SystemProperties.getProperty ("java.security.policy");
+ String s = System.getProperty ("java.security.policy");
logger.log (Component.POLICY, "java.security.policy={0}", s);
if (s != null)
{
diff --git a/gnu/java/security/Registry.java b/gnu/java/security/Registry.java
index b3df24c9e..053d71778 100644
--- a/gnu/java/security/Registry.java
+++ b/gnu/java/security/Registry.java
@@ -89,6 +89,18 @@ public interface Registry
String CAST_128_CIPHER = "cast-128";
+ // Key Wrapping Algorithm names and synonyms ...............................
+
+ String KWA_PREFIX = "kw-";
+ String AES_KWA = KWA_PREFIX + AES_CIPHER;
+ String AES128_KWA = AES_KWA + "128";
+ String AES192_KWA = AES_KWA + "192";
+ String AES256_KWA = AES_KWA + "256";
+ String RIJNDAEL_KWA = KWA_PREFIX + RIJNDAEL_CIPHER;
+
+ String TRIPLEDES_KWA = KWA_PREFIX + TRIPLEDES_CIPHER;
+ String DESEDE_KWA = KWA_PREFIX + DESEDE_CIPHER;
+
// Message digest algorithms and synonyms...................................
String WHIRLPOOL_HASH = "whirlpool";
diff --git a/gnu/java/security/key/dss/DSSKey.java b/gnu/java/security/key/dss/DSSKey.java
index 29205605b..657de8dd0 100644
--- a/gnu/java/security/key/dss/DSSKey.java
+++ b/gnu/java/security/key/dss/DSSKey.java
@@ -38,11 +38,12 @@ exception statement from your version. */
package gnu.java.security.key.dss;
-import gnu.classpath.SystemProperties;
import gnu.java.security.Registry;
+import gnu.java.security.action.GetPropertyAction;
import gnu.java.security.util.FormatUtil;
import java.math.BigInteger;
+import java.security.AccessController;
import java.security.Key;
import java.security.interfaces.DSAKey;
import java.security.interfaces.DSAParams;
@@ -59,6 +60,10 @@ import java.security.spec.DSAParameterSpec;
* of the byte sequences and the implementation details are given in each of the
* relevant <code>getEncoded()</code> methods of each of the private and
* public keys.
+ * <p>
+ * <b>IMPORTANT</b>: Under certain circumstances (e.g. in an X.509 certificate
+ * with inherited AlgorithmIdentifier's parameters of a SubjectPublicKeyInfo
+ * element) these three MPIs may be <code>null</code>.
*
* @see DSSPrivateKey#getEncoded
* @see DSSPublicKey#getEncoded
@@ -144,6 +149,11 @@ public abstract class DSSKey
* Returns <code>true</code> if the designated object is an instance of
* {@link DSAKey} and has the same DSS (Digital Signature Standard) parameter
* values as this one.
+ * <p>
+ * Always returns <code>false</code> if the MPIs of this key are
+ * <i>inherited</i>. This may be the case when the key is re-constructed from
+ * an X.509 certificate with absent or NULL AlgorithmIdentifier's parameters
+ * field.
*
* @param obj the other non-null DSS key to compare to.
* @return <code>true</code> if the designated object is of the same type
@@ -151,6 +161,9 @@ public abstract class DSSKey
*/
public boolean equals(Object obj)
{
+ if (hasInheritedParameters())
+ return false;
+
if (obj == null)
return false;
@@ -167,16 +180,32 @@ public abstract class DSSKey
{
if (str == null)
{
- String ls = SystemProperties.getProperty("line.separator");
- str = new StringBuilder(ls)
- .append("defaultFormat=").append(defaultFormat).append(",").append(ls)
- .append("p=0x").append(p.toString(16)).append(",").append(ls)
- .append("q=0x").append(q.toString(16)).append(",").append(ls)
- .append("g=0x").append(g.toString(16))
- .toString();
+ String ls = (String) AccessController.doPrivileged(new GetPropertyAction("line.separator"));
+ StringBuilder sb = new StringBuilder(ls)
+ .append("defaultFormat=").append(defaultFormat).append(",")
+ .append(ls);
+ if (hasInheritedParameters())
+ sb.append("p=inherited,").append(ls)
+ .append("q=inherited,").append(ls)
+ .append("g=inherited");
+ else
+ sb.append("p=0x").append(p.toString(16)).append(",").append(ls)
+ .append("q=0x").append(q.toString(16)).append(",").append(ls)
+ .append("g=0x").append(g.toString(16));
+ str = sb.toString();
}
return str;
}
public abstract byte[] getEncoded(int format);
+
+ /**
+ * @return <code>true</code> if <code>p</code>, <code>q</code> and
+ * <code>g</code> are all <code>null</code>. Returns
+ * <code>false</code> otherwise.
+ */
+ public boolean hasInheritedParameters()
+ {
+ return p == null && q == null && g == null;
+ }
}
diff --git a/gnu/java/security/key/dss/DSSKeyPairX509Codec.java b/gnu/java/security/key/dss/DSSKeyPairX509Codec.java
index 5ddd6e0d6..a5e8e9d47 100644
--- a/gnu/java/security/key/dss/DSSKeyPairX509Codec.java
+++ b/gnu/java/security/key/dss/DSSKeyPairX509Codec.java
@@ -94,9 +94,15 @@ public class DSSKeyPairX509Codec
* g INTEGER
* }
* </pre>
- *
- * <p>The <i>subjectPublicKey</i> field, which is a BIT STRING, contains the
- * DER-encoded form of the DSA public key as an INTEGER.</p>
+ * <p>
+ * Note that RFC-3280 (page 79) implies that some certificates MAY have an
+ * absent, or NULL, parameters field in their AlgorithmIdentifier element,
+ * implying that those parameters MUST be <i>inherited</i> from another
+ * certificate. This implementation, encodes a <i>NULL</i> element as the DER
+ * value of the parameters field when such is the case.
+ * <p>
+ * The <i>subjectPublicKey</i> field, which is a BIT STRING, contains the
+ * DER-encoded form of the DSA public key as an INTEGER.
*
* <pre>
* DSAPublicKey ::= INTEGER -- public key, Y
@@ -118,20 +124,25 @@ public class DSSKeyPairX509Codec
DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, DSA_ALG_OID);
DSSPublicKey dssKey = (DSSPublicKey) key;
- BigInteger p = dssKey.getParams().getP();
- BigInteger q = dssKey.getParams().getQ();
- BigInteger g = dssKey.getParams().getG();
- BigInteger y = dssKey.getY();
-
- DERValue derP = new DERValue(DER.INTEGER, p);
- DERValue derQ = new DERValue(DER.INTEGER, q);
- DERValue derG = new DERValue(DER.INTEGER, g);
-
- ArrayList params = new ArrayList(3);
- params.add(derP);
- params.add(derQ);
- params.add(derG);
- DERValue derParams = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, params);
+ DERValue derParams;
+ if (dssKey.hasInheritedParameters())
+ derParams = new DERValue(DER.NULL, null);
+ else
+ {
+ BigInteger p = dssKey.getParams().getP();
+ BigInteger q = dssKey.getParams().getQ();
+ BigInteger g = dssKey.getParams().getG();
+
+ DERValue derP = new DERValue(DER.INTEGER, p);
+ DERValue derQ = new DERValue(DER.INTEGER, q);
+ DERValue derG = new DERValue(DER.INTEGER, g);
+
+ ArrayList params = new ArrayList(3);
+ params.add(derP);
+ params.add(derQ);
+ params.add(derG);
+ derParams = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, params);
+ }
ArrayList algorithmID = new ArrayList(2);
algorithmID.add(derOID);
@@ -139,6 +150,7 @@ public class DSSKeyPairX509Codec
DERValue derAlgorithmID = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
algorithmID);
+ BigInteger y = dssKey.getY();
DERValue derDSAPublicKey = new DERValue(DER.INTEGER, y);
byte[] yBytes = derDSAPublicKey.getEncoded();
DERValue derSPK = new DERValue(DER.BIT_STRING, new BitString(yBytes));
@@ -185,7 +197,10 @@ public class DSSKeyPairX509Codec
if (input == null)
throw new InvalidParameterException("Input bytes MUST NOT be null");
- BigInteger p, g, q, y;
+ BigInteger p = null;
+ BigInteger g = null;
+ BigInteger q = null;
+ BigInteger y;
DERReader der = new DERReader(input);
try
{
@@ -203,20 +218,35 @@ public class DSSKeyPairX509Codec
if (! algOID.equals(DSA_ALG_OID))
throw new InvalidParameterException("Unexpected OID: " + algOID);
- DERValue derParams = der.read();
- DerUtil.checkIsConstructed(derParams, "Wrong DSS Parameters field");
-
DERValue val = der.read();
- DerUtil.checkIsBigInteger(val, "Wrong P field");
- p = (BigInteger) val.getValue();
- val = der.read();
- DerUtil.checkIsBigInteger(val, "Wrong Q field");
- q = (BigInteger) val.getValue();
- val = der.read();
- DerUtil.checkIsBigInteger(val, "Wrong G field");
- g = (BigInteger) val.getValue();
-
- val = der.read();
+ // RFC-3280, page 79 states: "If the subjectPublicKeyInfo field of the
+ // certificate contains an algorithm field with null parameters or
+ // parameters are omitted, compare the certificate subjectPublicKey
+ // algorithm to the working_public_key_algorithm. If the certificate
+ // subjectPublicKey algorithm and the working_public_key_algorithm are
+ // different, set the working_public_key_parameters to null."
+ // in other words, the parameters field of an AlgorithmIdentifier
+ // element MAY NOT be present at all, or if present MAY be NULL!
+ // the Mauve test ValidDSAParameterInheritenceTest5, in
+ // gnu.testlet.java.security.cert.pkix.pkits, is/was failing because
+ // of this.
+ if (val.getTag() == DER.NULL)
+ val = der.read();
+ else if (val.isConstructed())
+ {
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong P field");
+ p = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong Q field");
+ q = (BigInteger) val.getValue();
+ val = der.read();
+ DerUtil.checkIsBigInteger(val, "Wrong G field");
+ g = (BigInteger) val.getValue();
+
+ val = der.read();
+ }
+
if (! (val.getValue() instanceof BitString))
throw new InvalidParameterException("Wrong SubjectPublicKey field");
diff --git a/gnu/java/security/key/dss/DSSPrivateKey.java b/gnu/java/security/key/dss/DSSPrivateKey.java
index 6c64987bc..6ed8de846 100644
--- a/gnu/java/security/key/dss/DSSPrivateKey.java
+++ b/gnu/java/security/key/dss/DSSPrivateKey.java
@@ -39,11 +39,12 @@ exception statement from your version. */
package gnu.java.security.key.dss;
import gnu.java.security.Configuration;
-import gnu.classpath.SystemProperties;
import gnu.java.security.Registry;
+import gnu.java.security.action.GetPropertyAction;
import gnu.java.security.key.IKeyPairCodec;
import java.math.BigInteger;
+import java.security.AccessController;
import java.security.PrivateKey;
import java.security.interfaces.DSAPrivateKey;
@@ -188,7 +189,8 @@ public class DSSPrivateKey
{
if (str == null)
{
- String ls = SystemProperties.getProperty("line.separator");
+ String ls = (String) AccessController.doPrivileged
+ (new GetPropertyAction("line.separator"));
str = new StringBuilder(this.getClass().getName()).append("(")
.append(super.toString()).append(",").append(ls)
.append("x=0x").append(Configuration.DEBUG ? x.toString(16)
diff --git a/gnu/java/security/key/dss/DSSPublicKey.java b/gnu/java/security/key/dss/DSSPublicKey.java
index fa3ad04d0..9e1c4cf0a 100644
--- a/gnu/java/security/key/dss/DSSPublicKey.java
+++ b/gnu/java/security/key/dss/DSSPublicKey.java
@@ -38,11 +38,12 @@ exception statement from your version. */
package gnu.java.security.key.dss;
-import gnu.classpath.SystemProperties;
import gnu.java.security.Registry;
+import gnu.java.security.action.GetPropertyAction;
import gnu.java.security.key.IKeyPairCodec;
import java.math.BigInteger;
+import java.security.AccessController;
import java.security.PublicKey;
import java.security.interfaces.DSAPublicKey;
@@ -187,7 +188,8 @@ public class DSSPublicKey
{
if (str == null)
{
- String ls = SystemProperties.getProperty("line.separator");
+ String ls = (String) AccessController.doPrivileged
+ (new GetPropertyAction("line.separator"));
str = new StringBuilder(this.getClass().getName()).append("(")
.append(super.toString()).append(",").append(ls)
.append("y=0x").append(y.toString(16)).append(ls)
diff --git a/gnu/java/security/key/rsa/GnuRSAKey.java b/gnu/java/security/key/rsa/GnuRSAKey.java
index 6ff740184..4bdce4011 100644
--- a/gnu/java/security/key/rsa/GnuRSAKey.java
+++ b/gnu/java/security/key/rsa/GnuRSAKey.java
@@ -38,11 +38,12 @@ exception statement from your version. */
package gnu.java.security.key.rsa;
-import gnu.classpath.SystemProperties;
import gnu.java.security.Registry;
+import gnu.java.security.action.GetPropertyAction;
import gnu.java.security.util.FormatUtil;
import java.math.BigInteger;
+import java.security.AccessController;
import java.security.Key;
import java.security.interfaces.RSAKey;
@@ -160,7 +161,8 @@ public abstract class GnuRSAKey
{
if (str == null)
{
- String ls = SystemProperties.getProperty("line.separator");
+ String ls = (String) AccessController.doPrivileged
+ (new GetPropertyAction("line.separator"));
str = new StringBuilder(ls)
.append("defaultFormat=").append(defaultFormat).append(",").append(ls)
.append("n=0x").append(n.toString(16)).append(",").append(ls)
diff --git a/gnu/java/security/key/rsa/GnuRSAPrivateKey.java b/gnu/java/security/key/rsa/GnuRSAPrivateKey.java
index ef466d020..00a1b822a 100644
--- a/gnu/java/security/key/rsa/GnuRSAPrivateKey.java
+++ b/gnu/java/security/key/rsa/GnuRSAPrivateKey.java
@@ -39,11 +39,12 @@ exception statement from your version. */
package gnu.java.security.key.rsa;
import gnu.java.security.Configuration;
-import gnu.classpath.SystemProperties;
+import gnu.java.security.action.GetPropertyAction;
import gnu.java.security.Registry;
import gnu.java.security.key.IKeyPairCodec;
import java.math.BigInteger;
+import java.security.AccessController;
import java.security.PrivateKey;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPrivateKey;
@@ -286,7 +287,8 @@ public class GnuRSAPrivateKey
{
if (str == null)
{
- String ls = SystemProperties.getProperty("line.separator");
+ String ls = (String) AccessController.doPrivileged
+ (new GetPropertyAction("line.separator"));
str = new StringBuilder(this.getClass().getName()).append("(")
.append(super.toString()).append(",").append(ls)
.append("d=0x").append(Configuration.DEBUG ? d.toString(16)
diff --git a/gnu/java/security/key/rsa/GnuRSAPublicKey.java b/gnu/java/security/key/rsa/GnuRSAPublicKey.java
index 1bbca4fa2..fe28d0ba3 100644
--- a/gnu/java/security/key/rsa/GnuRSAPublicKey.java
+++ b/gnu/java/security/key/rsa/GnuRSAPublicKey.java
@@ -38,11 +38,12 @@ exception statement from your version. */
package gnu.java.security.key.rsa;
-import gnu.classpath.SystemProperties;
import gnu.java.security.Registry;
+import gnu.java.security.action.GetPropertyAction;
import gnu.java.security.key.IKeyPairCodec;
import java.math.BigInteger;
+import java.security.AccessController;
import java.security.PublicKey;
import java.security.interfaces.RSAPublicKey;
@@ -175,7 +176,8 @@ public class GnuRSAPublicKey
{
if (str == null)
{
- String ls = SystemProperties.getProperty("line.separator");
+ String ls = (String) AccessController.doPrivileged
+ (new GetPropertyAction("line.separator"));
str = new StringBuilder(this.getClass().getName()).append("(")
.append(super.toString()).append(",").append(ls)
.append(")")
diff --git a/gnu/java/security/key/rsa/RSAKeyPairPKCS8Codec.java b/gnu/java/security/key/rsa/RSAKeyPairPKCS8Codec.java
index 7fa9d0102..7a51d0a0d 100644
--- a/gnu/java/security/key/rsa/RSAKeyPairPKCS8Codec.java
+++ b/gnu/java/security/key/rsa/RSAKeyPairPKCS8Codec.java
@@ -98,6 +98,9 @@ public class RSAKeyPairPKCS8Codec
* }
* </pre>
* <p>
+ * As indicated in RFC-2459: "The parameters field shall have ASN.1 type NULL
+ * for this algorithm identifier.".
+ * <p>
* The <i>privateKey</i> field, which is an OCTET STRING, contains the
* DER-encoded form of the RSA private key defined as:
* <pre>
@@ -140,8 +143,9 @@ public class RSAKeyPairPKCS8Codec
DERValue derOID = new DERValue(DER.OBJECT_IDENTIFIER, RSA_ALG_OID);
- ArrayList algorithmID = new ArrayList(1);
+ ArrayList algorithmID = new ArrayList(2);
algorithmID.add(derOID);
+ algorithmID.add(new DERValue(DER.NULL, null));
DERValue derAlgorithmID = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
algorithmID);
@@ -238,9 +242,12 @@ public class RSAKeyPairPKCS8Codec
if (! algOID.equals(RSA_ALG_OID))
throw new InvalidParameterException("Unexpected OID: " + algOID);
+ // rfc-2459 states that this field is OPTIONAL but NULL if/when present
DERValue val = der.read();
- byte[] pkBytes = (byte[]) val.getValue();
+ if (val.getTag() == DER.NULL)
+ val = der.read();
+ byte[] pkBytes = (byte[]) val.getValue();
der = new DERReader(pkBytes);
DERValue derRSAPrivateKey = der.read();
DerUtil.checkIsConstructed(derRSAPrivateKey, "Wrong RSAPrivateKey field");
diff --git a/gnu/classpath/ByteArray.java b/gnu/java/security/util/ByteArray.java
index 6307b8abd..0d04d9127 100644
--- a/gnu/classpath/ByteArray.java
+++ b/gnu/java/security/util/ByteArray.java
@@ -36,7 +36,7 @@ obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-package gnu.classpath;
+package gnu.java.security.util;
import java.io.PrintWriter;
import java.io.StringWriter;
diff --git a/gnu/java/security/util/IntegerUtil.java b/gnu/java/security/util/IntegerUtil.java
new file mode 100644
index 000000000..f07130808
--- /dev/null
+++ b/gnu/java/security/util/IntegerUtil.java
@@ -0,0 +1,109 @@
+/* IntegerUtil.java -- JDK 5 Integer methods with 1.4 API
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.util;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Utility class which offers Integer related methods found in RI's version 5
+ * but written with RI's 1.4 API.
+ */
+public abstract class IntegerUtil
+{
+ /** Maximum size of our cache of constructed Integers. */
+ private static final int CACHE_SIZE = 100;
+ /** LRU (Least Recently Used) cache, of the last accessed 100 Integers. */
+ private static final Map cache = new LinkedHashMap(CACHE_SIZE + 1, 0.75F, true)
+ {
+ public boolean removeEldestEntry(Map.Entry entry)
+ {
+ return size() > CACHE_SIZE;
+ }
+ };
+
+ /** Trivial private constructor to enforce Singleton usage. */
+ private IntegerUtil()
+ {
+ super();
+ }
+
+ /**
+ * Similar to {@link Integer#valueOf(String)} except it caches the result in
+ * a local LRU cache of 100 elements, organized by access order.
+ * <p>
+ * This method MUST be used in the gnu.java.security and gnu.javax.crypto
+ * packages to ensure they would work with a version 1.4 only of the Java
+ * class library API.
+ *
+ * @param aString a string representation of an integer.
+ * @return the {@link Integer} object representing the designated string.
+ */
+ public static final Integer valueOf(String aString)
+ {
+ Integer result;
+ synchronized (cache)
+ {
+ result = (Integer) cache.get(aString);
+ if (result == null)
+ {
+ result = Integer.valueOf(aString);
+ cache.put(aString, result);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Simulates the <code>valueOf(int)</code> method found in {@link Integer} of
+ * the RI's version 1.5 using a local LRU cache of 100 elements, organized by
+ * access order.
+ * <p>
+ * This method MUST be used in the gnu.java.security and gnu.javax.crypto
+ * packages to ensure they would work with a version 1.4 only of the Java
+ * class library API.
+ *
+ * @param anInt a decimal integer.
+ * @return the {@link Integer} object representing the designated primitive.
+ */
+ public static final Integer valueOf(int anInt)
+ {
+ return valueOf(Integer.toString(anInt, 10));
+ }
+}
diff --git a/gnu/java/util/prefs/GConfBasedPreferences.java b/gnu/java/util/prefs/GConfBasedPreferences.java
index cbedac5c8..5702751cf 100644
--- a/gnu/java/util/prefs/GConfBasedPreferences.java
+++ b/gnu/java/util/prefs/GConfBasedPreferences.java
@@ -72,6 +72,7 @@ import java.util.prefs.BackingStoreException;
* <br />
*
* @author Mario Torre <neugens@limasoftware.net>
+ * @version 1.0.1
*/
public class GConfBasedPreferences
extends AbstractPreferences
@@ -84,7 +85,7 @@ public class GConfBasedPreferences
private static GConfNativePeer backend = new GConfNativePeer();
/** Default user root path */
- private static final String DEFAULT_USER_ROOT = "/apps/java";
+ private static final String DEFAULT_USER_ROOT = "/apps/classpath";
/** Default system root path */
private static final String DEFAULT_SYSTEM_ROOT = "/system";
@@ -129,7 +130,13 @@ public class GConfBasedPreferences
this.isUser = isUser;
// stores the fully qualified name of this node
- this.node = this.getRealRoot(isUser) + this.absolutePath();
+ String absolutePath = this.absolutePath();
+ if (absolutePath != null && absolutePath.endsWith("/"))
+ {
+ absolutePath = absolutePath.substring(0, absolutePath.length() - 1);
+ }
+
+ this.node = this.getRealRoot(isUser) + absolutePath;
boolean nodeExist = backend.nodeExist(this.node);
@@ -356,9 +363,8 @@ public class GConfBasedPreferences
*/
private String getGConfKey(String key)
{
-
String nodeName = "";
-
+
if (this.node.endsWith("/"))
{
nodeName = this.node + key;
diff --git a/gnu/java/util/prefs/gconf/GConfNativePeer.java b/gnu/java/util/prefs/gconf/GConfNativePeer.java
index 8d773f916..f1cb62787 100644
--- a/gnu/java/util/prefs/gconf/GConfNativePeer.java
+++ b/gnu/java/util/prefs/gconf/GConfNativePeer.java
@@ -45,7 +45,7 @@ import java.util.prefs.BackingStoreException;
* Native peer for GConf based preference backend.
*
* @author Mario Torre <neugens@limasoftware.net>
- * @version 1.0
+ * @version 1.0.1
*/
public final class GConfNativePeer
{
@@ -73,10 +73,6 @@ public final class GConfNativePeer
*/
public boolean nodeExist(String node)
{
- if (node.endsWith("/"))
- {
- node = node.substring(0, node.length() - 1);
- }
return gconf_client_dir_exists(node);
}
@@ -89,10 +85,6 @@ public final class GConfNativePeer
*/
public void startWatchingNode(String node)
{
- if (node.endsWith("/"))
- {
- node = node.substring(0, node.length() - 1);
- }
gconf_client_add_dir(node);
}
@@ -105,16 +97,14 @@ public final class GConfNativePeer
*/
public void stopWatchingNode(String node)
{
- if (node.endsWith("/"))
- {
- node = node.substring(0, node.length() - 1);
- }
gconf_client_remove_dir(node);
}
/**
* Change the value of key to val. Automatically creates the key if it didn't
* exist before (ie it was unset or it only had a default value).
+ * Key names must be valid GConf key names, that is, there can be more
+ * restrictions than for normal Preference Backend.
*
* @param key the key to alter (or add).
* @param value the new value for this key.
@@ -122,10 +112,6 @@ public final class GConfNativePeer
*/
public boolean setString(String key, String value)
{
- if (key.endsWith("/"))
- {
- key = key.substring(0, key.length() - 1);
- }
return gconf_client_set_string(key, value);
}
@@ -139,10 +125,6 @@ public final class GConfNativePeer
*/
public boolean unset(String key)
{
- if (key.endsWith("/"))
- {
- key = key.substring(0, key.length() - 1);
- }
return gconf_client_unset(key);
}
@@ -154,16 +136,12 @@ public final class GConfNativePeer
*/
public String getKey(String key)
{
- if (key.endsWith("/"))
- {
- key = key.substring(0, key.length() - 1);
- }
return gconf_client_get_string(key);
}
/**
* Lists the key in the given node. Does not list subnodes. Keys names are the
- * stripped names (name relative to the current node) of the kyes stored in
+ * stripped names (name relative to the current node) of the keys stored in
* this node.
*
* @param node the node where keys are stored.
@@ -172,10 +150,6 @@ public final class GConfNativePeer
*/
public List getKeys(String node) throws BackingStoreException
{
- if (node.endsWith("/"))
- {
- node = node.substring(0, node.length() - 1);
- }
return gconf_client_gconf_client_all_keys(node);
}
@@ -188,10 +162,6 @@ public final class GConfNativePeer
*/
public List getChildrenNodes(String node) throws BackingStoreException
{
- if (node.endsWith("/"))
- {
- node = node.substring(0, node.length() - 1);
- }
return gconf_client_gconf_client_all_nodes(node);
}
@@ -226,33 +196,99 @@ public final class GConfNativePeer
* the main java class.
*/
- /** */
+ /**
+ * Initialize the GConf native peer and enable the object cache.
+ * It is meant to be used by the static initializer.
+ */
native static final private void init_id_cache();
+ /**
+ * Initialize the GConf native peer. This is meant to be used by the
+ * class constructor.
+ */
native static final private void init_class();
+ /**
+ * Class finalizer.
+ */
native static final private void finalize_class();
+ /**
+ * Queries the GConf database to see if the given node exists, returning
+ * true if the node exist, false otherwise.
+ *
+ * @param node the node to query for existence.
+ * @return true if the node exist, false otherwise.
+ */
native static final protected boolean gconf_client_dir_exists(String node);
+ /**
+ * Adds the given node to the list of nodes that GConf watches for
+ * changes.
+ *
+ * @param node the node to watch for changes.
+ */
native static final protected void gconf_client_add_dir(String node);
+ /**
+ * Removes the given node from the list of nodes that GConf watches for
+ * changes.
+ *
+ * @param node the node to remove from from the list of watched nodes.
+ */
native static final protected void gconf_client_remove_dir(String node);
+ /**
+ * Sets the given key/value pair into the GConf database.
+ * The key must be a valid GConf key.
+ *
+ * @param key the key to store in the GConf database
+ * @param value the value to associate to the given key.
+ * @return true if the change has effect, false otherwise.
+ */
native static final protected boolean gconf_client_set_string(String key,
String value);
+ /**
+ * Returns the key associated to the given key. Null is returned if the
+ * key is not valid.
+ *
+ * @param key the key to return the value of.
+ * @return The value associated to the given key, or null.
+ */
native static final protected String gconf_client_get_string(String key);
+ /**
+ * Usets the given key, removing the key from the database.
+ *
+ * @param key the key to remove.
+ * @return true if the operation success, false otherwise.
+ */
native static final protected boolean gconf_client_unset(String key);
+ /**
+ * Suggest to the GConf native peer a sync with the database.
+ *
+ */
native static final protected void gconf_client_suggest_sync();
- native static final protected List gconf_client_gconf_client_all_nodes(
- String node);
+ /**
+ * Returns a list of all nodes under the given node.
+ *
+ * @param node the source node.
+ * @return A list of nodes under the given source node.
+ */
+ native
+ static final protected List gconf_client_gconf_client_all_nodes(String node);
- native static final protected List gconf_client_gconf_client_all_keys(
- String node);
+ /**
+ * Returns a list of all keys stored in the given node.
+ *
+ * @param node the source node.
+ * @return A list of all keys stored in the given node.
+ */
+ native
+ static final protected List gconf_client_gconf_client_all_keys(String node);
static
{
diff --git a/gnu/java/util/regex/RE.java b/gnu/java/util/regex/RE.java
index cd12aab8f..1aab3b781 100644
--- a/gnu/java/util/regex/RE.java
+++ b/gnu/java/util/regex/RE.java
@@ -130,7 +130,7 @@ public class RE extends REToken {
private static final String VERSION = "1.1.5-dev";
// The localized strings are kept in a separate file
- private static ResourceBundle messages = PropertyResourceBundle.getBundle("gnu/regexp/MessagesBundle", Locale.getDefault());
+ private static ResourceBundle messages = PropertyResourceBundle.getBundle("gnu/java/util/regex/MessagesBundle", Locale.getDefault());
// These are, respectively, the first and last tokens in our linked list
// If there is only one token, firstToken == lastToken
@@ -750,7 +750,20 @@ public class RE extends REToken {
else if ((unit.ch == '^') && !(unit.bk || quot)) {
addToken(currentToken);
currentToken = null;
- addToken(new RETokenStart(subIndex,((cflags & REG_MULTILINE) > 0) ? syntax.getLineSeparator() : null));
+ RETokenStart token = null;
+ if ((cflags & REG_MULTILINE) > 0) {
+ String sep = syntax.getLineSeparator();
+ if (sep == null) {
+ token = new RETokenStart(subIndex, null, true);
+ }
+ else {
+ token = new RETokenStart(subIndex, sep);
+ }
+ }
+ else {
+ token = new RETokenStart(subIndex, null);
+ }
+ addToken(token);
}
// END OF LINE OPERATOR
@@ -759,7 +772,20 @@ public class RE extends REToken {
else if ((unit.ch == '$') && !(unit.bk || quot)) {
addToken(currentToken);
currentToken = null;
- addToken(new RETokenEnd(subIndex,((cflags & REG_MULTILINE) > 0) ? syntax.getLineSeparator() : null));
+ RETokenEnd token = null;
+ if ((cflags & REG_MULTILINE) > 0) {
+ String sep = syntax.getLineSeparator();
+ if (sep == null) {
+ token = new RETokenEnd(subIndex, null, true);
+ }
+ else {
+ token = new RETokenEnd(subIndex, sep);
+ }
+ }
+ else {
+ token = new RETokenEnd(subIndex, null);
+ }
+ addToken(token);
}
// MATCH-ANY-CHARACTER OPERATOR (except possibly newline and null)
diff --git a/gnu/java/util/regex/RETokenEnd.java b/gnu/java/util/regex/RETokenEnd.java
index c846415e1..00efdb6a7 100644
--- a/gnu/java/util/regex/RETokenEnd.java
+++ b/gnu/java/util/regex/RETokenEnd.java
@@ -43,10 +43,18 @@ final class RETokenEnd extends REToken {
* Indicates whether this token should match on a line break.
*/
private String newline;
+ private boolean check_java_line_terminators;
RETokenEnd(int subIndex,String newline) {
super(subIndex);
this.newline = newline;
+ this.check_java_line_terminators = false;
+ }
+
+ RETokenEnd(int subIndex, String newline, boolean b) {
+ super(subIndex);
+ this.newline = newline;
+ this.check_java_line_terminators = b;
}
int getMaximumLength() {
@@ -58,6 +66,18 @@ final class RETokenEnd extends REToken {
if (ch == CharIndexed.OUT_OF_BOUNDS)
return ((mymatch.eflags & RE.REG_NOTEOL)>0) ?
null : mymatch;
+ if (check_java_line_terminators) {
+ if (ch == '\n') {
+ char ch1 = input.charAt(mymatch.index - 1);
+ if (ch1 == '\r') return null;
+ return mymatch;
+ }
+ if (ch == '\r') return mymatch;
+ if (ch == '\u0085') return mymatch; // A next-line character
+ if (ch == '\u2028') return mymatch; // A line-separator character
+ if (ch == '\u2029') return mymatch; // A paragraph-separator character
+ return null;
+ }
if (newline != null) {
char z;
int i = 0; // position in newline
diff --git a/gnu/java/util/regex/RETokenStart.java b/gnu/java/util/regex/RETokenStart.java
index 56bc36129..aa5f0c914 100644
--- a/gnu/java/util/regex/RETokenStart.java
+++ b/gnu/java/util/regex/RETokenStart.java
@@ -39,10 +39,18 @@ package gnu.java.util.regex;
class RETokenStart extends REToken {
private String newline; // matches after a newline
+ private boolean check_java_line_terminators;
RETokenStart(int subIndex, String newline) {
super(subIndex);
this.newline = newline;
+ this.check_java_line_terminators = false;
+ }
+
+ RETokenStart(int subIndex, String newline, boolean b) {
+ super(subIndex);
+ this.newline = newline;
+ this.check_java_line_terminators = b;
}
int getMaximumLength() {
@@ -53,6 +61,21 @@ class RETokenStart extends REToken {
// charAt(index-n) may be unknown on a Reader/InputStream. FIXME
// Match after a newline if in multiline mode
+ if (check_java_line_terminators) {
+ char ch = input.charAt(mymatch.index - 1);
+ if (ch != CharIndexed.OUT_OF_BOUNDS) {
+ if (ch == '\n') return mymatch;
+ if (ch == '\r') {
+ char ch1 = input.charAt(mymatch.index);
+ if (ch1 != '\n') return mymatch;
+ return null;
+ }
+ if (ch == '\u0085') return mymatch; // A next-line character
+ if (ch == '\u2028') return mymatch; // A line-separator character
+ if (ch == '\u2029') return mymatch; // A paragraph-separator character
+ }
+ }
+
if (newline != null) {
int len = newline.length();
if (mymatch.offset >= len) {
diff --git a/gnu/javax/crypto/RSACipherImpl.java b/gnu/javax/crypto/RSACipherImpl.java
index 90fde9d7b..60504ecce 100644
--- a/gnu/javax/crypto/RSACipherImpl.java
+++ b/gnu/javax/crypto/RSACipherImpl.java
@@ -38,9 +38,9 @@ exception statement from your version. */
package gnu.javax.crypto;
-import gnu.classpath.ByteArray;
import gnu.classpath.debug.Component;
import gnu.classpath.debug.SystemLogger;
+import gnu.java.security.util.ByteArray;
import java.math.BigInteger;
import java.security.AlgorithmParameters;
diff --git a/gnu/javax/crypto/cipher/DES.java b/gnu/javax/crypto/cipher/DES.java
index 2bb897177..3ced62c3f 100644
--- a/gnu/javax/crypto/cipher/DES.java
+++ b/gnu/javax/crypto/cipher/DES.java
@@ -299,7 +299,7 @@ public class DES
*/
public static void adjustParity(byte[] kb, int offset)
{
- for (int i = offset; i < KEY_SIZE; i++)
+ for (int i = offset; i < offset + KEY_SIZE; i++)
kb[i] ^= (PARITY[kb[i] & 0xff] == 8) ? 1 : 0;
}
diff --git a/gnu/javax/crypto/cipher/TripleDES.java b/gnu/javax/crypto/cipher/TripleDES.java
index 7aeb4ea96..1e98bfc83 100644
--- a/gnu/javax/crypto/cipher/TripleDES.java
+++ b/gnu/javax/crypto/cipher/TripleDES.java
@@ -40,17 +40,21 @@ package gnu.javax.crypto.cipher;
import gnu.java.security.Registry;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.security.InvalidKeyException;
/**
* Triple-DES, 3DES, or DESede is a <i>combined cipher</i> that uses three
- * iterations of the Data Encryption Standard cipher to improve the security (at
- * the cost of speed) of plain DES.
+ * iterations of the Data Encryption Standard cipher to theoretically improve
+ * the security of plain DES, at the cost of speed.
* <p>
- * Triple-DES runs the DES algorithm three times with three independent 56 bit
- * keys. To encrypt:
+ * Triple-DES runs the DES algorithm three times with one, two or three
+ * independent 56-bit (DES) keys. When used with one DES key, the cipher behaves
+ * exactly like a (slower) DES.
+ * <p>
+ * To encrypt:
* <blockquote><i>C<sub>i</sub> = E<sub>k3</sub> ( E<sub>k2</sub><sup>-1</sup> (
* E<sub>k1</sub> ( P<sub>i</sub> )))</i>
* </blockquote>
@@ -75,10 +79,8 @@ public class TripleDES
{
/** Triple-DES only operates on 64 bit blocks. */
public static final int BLOCK_SIZE = 8;
-
- /** Triple-DES uses 168 bits of a parity-adjusted 192 bit key. */
+ /** By default, Triple-DES uses 168 bits of a parity-adjusted 192 bit key. */
public static final int KEY_SIZE = 24;
-
/** The underlying DES instance. */
private DES des;
@@ -92,21 +94,45 @@ public class TripleDES
}
/**
- * Transform a key so it will be parity adjusted.
+ * Convenience method which calls the method with same name and three
+ * arguments, passing <code>3</code> as the value of the first parameter.
*
* @param kb The key bytes to adjust.
* @param offset The starting offset into the key bytes.
- * @see DES#adjustParity(byte[],int)
*/
public static void adjustParity(byte[] kb, int offset)
{
+ adjustParity(3, kb, offset);
+ }
+
+ /**
+ * Adjusts, in-situ, the parity of the designated bytes, so they can be used
+ * as DES keys for a 3-DES 1-, 2- or 3-key cipher.
+ *
+ * @param keyCount the number of independent DES keys. Can be either
+ * <code>1</code>, <code>2</code> or <code>3</code>. Any other value
+ * will cause an {@link IllegalArgumentException} to be raised.
+ * @param kb the array containing the key bytes to adjust. MUST have at least
+ * <code>8 * keyCount</code> bytes starting at offset position
+ * <code>offset</code>, otherwise an
+ * {@link ArrayIndexOutOfBoundsException} will be raised.
+ * @param offset the starting offset into the array.
+ * @see DES#adjustParity(byte[],int)
+ */
+ public static void adjustParity(int keyCount, byte[] kb, int offset)
+ {
+ if (keyCount < 1 || keyCount > 3)
+ throw new IllegalArgumentException("Invalid keyCount value: " + keyCount);
DES.adjustParity(kb, offset);
- DES.adjustParity(kb, offset + 8);
- DES.adjustParity(kb, offset + 16);
+ if (keyCount > 1)
+ DES.adjustParity(kb, offset + 8);
+ if (keyCount > 2)
+ DES.adjustParity(kb, offset + 16);
}
/**
- * Tests if a byte array has already been parity adjusted.
+ * Convenience method which calls the method with same name and three
+ * arguments, passing <code>3</code> as the value of the first parameter.
*
* @param kb The key bytes to test.
* @param offset The starting offset into the key bytes.
@@ -117,9 +143,37 @@ public class TripleDES
*/
public static boolean isParityAdjusted(byte[] kb, int offset)
{
- return DES.isParityAdjusted(kb, offset)
- && DES.isParityAdjusted(kb, offset + 8)
- && DES.isParityAdjusted(kb, offset + 16);
+ return isParityAdjusted(3, kb, offset);
+ }
+
+ /**
+ * Tests if enough bytes, expected to be used as DES keys for a 3-DES 1-, 2-
+ * or 3-key cipher, located in a designated byte array, has already been
+ * parity adjusted.
+ *
+ * @param keyCount the number of independent DES keys. Can be either
+ * <code>1</code>, <code>2</code> or <code>3</code>. Any other value
+ * will cause an {@link IllegalArgumentException} to be raised.
+ * @param kb the array containing the key bytes to test. MUST have at least
+ * <code>8 * keyCount</code> bytes starting at offset position
+ * <code>offset</code>, otherwise an
+ * {@link ArrayIndexOutOfBoundsException} will be raised.
+ * @param offset the starting offset into the array.
+ * @return <code>true</code> if the bytes in <i>kb</i> starting at
+ * <i>offset</i> are parity adjusted.
+ * @see DES#isParityAdjusted(byte[],int)
+ * @see #adjustParity(int,byte[],int)
+ */
+ public static boolean isParityAdjusted(int keyCount, byte[] kb, int offset)
+ {
+ if (keyCount < 1 || keyCount > 3)
+ throw new IllegalArgumentException("Invalid keyCount value: " + keyCount);
+ boolean result = DES.isParityAdjusted(kb, offset);
+ if (keyCount > 1)
+ result = result && DES.isParityAdjusted(kb, offset + 8);
+ if (keyCount > 2)
+ result = result && DES.isParityAdjusted(kb, offset + 16);
+ return result;
}
public Object clone()
@@ -134,25 +188,49 @@ public class TripleDES
public Iterator keySizes()
{
- return Collections.singleton(Integer.valueOf(KEY_SIZE)).iterator();
+ ArrayList al = new ArrayList();
+ al.add(Integer.valueOf(8));
+ al.add(Integer.valueOf(16));
+ al.add(Integer.valueOf(24));
+ return Collections.unmodifiableList(al).iterator();
}
public Object makeKey(byte[] kb, int bs) throws InvalidKeyException
{
- if (kb.length != KEY_SIZE)
- throw new InvalidKeyException("TripleDES key must be 24 bytes");
- if (! isParityAdjusted(kb, 0))
- adjustParity(kb, 0);
+ if (kb.length != 8 && kb.length != 16 && kb.length != 24)
+ throw new InvalidKeyException("TripleDES key must be 8, 16 or 24 bytes: "
+ + kb.length);
+ Context ctx = new Context();
byte[] k1 = new byte[DES.KEY_SIZE];
- byte[] k2 = new byte[DES.KEY_SIZE];
- byte[] k3 = new byte[DES.KEY_SIZE];
System.arraycopy(kb, 0, k1, 0, DES.KEY_SIZE);
- System.arraycopy(kb, DES.KEY_SIZE, k2, 0, DES.KEY_SIZE);
- System.arraycopy(kb, 2 * DES.KEY_SIZE, k3, 0, DES.KEY_SIZE);
- Context ctx = new Context();
+ if (! DES.isParityAdjusted(k1, 0))
+ DES.adjustParity(k1, 0);
ctx.k1 = (DES.Context) des.makeKey(k1, bs);
- ctx.k2 = (DES.Context) des.makeKey(k2, bs);
- ctx.k3 = (DES.Context) des.makeKey(k3, bs);
+
+ if (kb.length == 8)
+ {
+ ctx.k2 = (DES.Context) des.makeKey(k1, bs);
+ ctx.k3 = (DES.Context) des.makeKey(k1, bs);
+ }
+ else
+ {
+ byte[] k2 = new byte[DES.KEY_SIZE];
+ System.arraycopy(kb, DES.KEY_SIZE, k2, 0, DES.KEY_SIZE);
+ if (! DES.isParityAdjusted(k2, 0))
+ DES.adjustParity(k2, 0);
+ ctx.k2 = (DES.Context) des.makeKey(k2, bs);
+
+ byte[] k3 = new byte[DES.KEY_SIZE];
+ if (kb.length == 16)
+ ctx.k3 = (DES.Context) des.makeKey(k1, bs);
+ else
+ {
+ System.arraycopy(kb, 2 * DES.KEY_SIZE, k3, 0, DES.KEY_SIZE);
+ if (! DES.isParityAdjusted(k3, 0))
+ DES.adjustParity(k3, 0);
+ ctx.k3 = (DES.Context) des.makeKey(k3, bs);
+ }
+ }
return ctx;
}
diff --git a/gnu/javax/crypto/jce/GnuCrypto.java b/gnu/javax/crypto/jce/GnuCrypto.java
index a65541ed1..8099fd13d 100644
--- a/gnu/javax/crypto/jce/GnuCrypto.java
+++ b/gnu/javax/crypto/jce/GnuCrypto.java
@@ -317,6 +317,16 @@ public final class GnuCrypto
put("Cipher.PBEWithHMacWhirlpoolAndTwofish",
gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.Twofish.class.getName());
+ // Key Wrapping Algorithm cipher
+ put("Cipher." + Registry.AES128_KWA,
+ gnu.javax.crypto.jce.cipher.AES128KeyWrapSpi.class.getName());
+ put("Cipher." + Registry.AES192_KWA,
+ gnu.javax.crypto.jce.cipher.AES192KeyWrapSpi.class.getName());
+ put("Cipher." + Registry.AES256_KWA,
+ gnu.javax.crypto.jce.cipher.AES256KeyWrapSpi.class.getName());
+ put("Cipher." + Registry.TRIPLEDES_KWA,
+ gnu.javax.crypto.jce.cipher.TripleDESKeyWrapSpi.class.getName());
+
// SecretKeyFactory interface to PBKDF2.
put("SecretKeyFactory.PBKDF2WithHMacHaval",
gnu.javax.crypto.jce.PBKDF2SecretKeyFactory.HMacHaval.class.getName());
diff --git a/gnu/javax/crypto/jce/cipher/AES128KeyWrapSpi.java b/gnu/javax/crypto/jce/cipher/AES128KeyWrapSpi.java
new file mode 100644
index 000000000..14ce480ae
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/AES128KeyWrapSpi.java
@@ -0,0 +1,54 @@
+/* AESKeyWrapSpi.java -- AES (128-bit key) Key Wrapping Algorithm JCE Adapter
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The JCE Cipher Adapter implementation over the GNU AES Key Wrapping
+ * Algorithm with a 128-bit key-size.
+ */
+public final class AES128KeyWrapSpi
+ extends AESKeyWrapSpi
+{
+ public AES128KeyWrapSpi()
+ {
+ super(Registry.AES128_KWA, 128 / 8, Registry.ECB_MODE);
+ }
+}
diff --git a/gnu/javax/crypto/jce/cipher/AES192KeyWrapSpi.java b/gnu/javax/crypto/jce/cipher/AES192KeyWrapSpi.java
new file mode 100644
index 000000000..784fc5a15
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/AES192KeyWrapSpi.java
@@ -0,0 +1,54 @@
+/* AES192KeyWrapSpi.java -- AES (192-bit key) Key Wrapping Algorithm JCE Adapter
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The JCE Cipher Adapter implementation over the GNU AES Key Wrapping
+ * Algorithm with a 192-bit key-size.
+ */
+public final class AES192KeyWrapSpi
+ extends AESKeyWrapSpi
+{
+ public AES192KeyWrapSpi()
+ {
+ super(Registry.AES192_KWA, 192 / 8, Registry.ECB_MODE);
+ }
+}
diff --git a/gnu/javax/crypto/jce/cipher/AES256KeyWrapSpi.java b/gnu/javax/crypto/jce/cipher/AES256KeyWrapSpi.java
new file mode 100644
index 000000000..dd7357b0e
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/AES256KeyWrapSpi.java
@@ -0,0 +1,54 @@
+/* AES256KeyWrapSpi.java -- AES (256-bit key) Key Wrapping Algorithm JCE Adapter
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The JCE Cipher Adapter implementation over the GNU AES Key Wrapping
+ * Algorithm with a 256-bit key-size.
+ */
+public final class AES256KeyWrapSpi
+ extends AESKeyWrapSpi
+{
+ public AES256KeyWrapSpi()
+ {
+ super(Registry.AES256_KWA, 256 / 8, Registry.ECB_MODE);
+ }
+}
diff --git a/gnu/javax/crypto/jce/cipher/AESKeyWrapSpi.java b/gnu/javax/crypto/jce/cipher/AESKeyWrapSpi.java
new file mode 100644
index 000000000..973f5890b
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/AESKeyWrapSpi.java
@@ -0,0 +1,88 @@
+/* AESKeyWrapSpi.java -- Common AES Key Wrapping Algorithm methods
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+/**
+ * Base abstract class to group common AES Key Wrapping Algorithm Adapter
+ * methods.
+ */
+abstract class AESKeyWrapSpi
+ extends KeyWrappingAlgorithmAdapter
+{
+ protected AESKeyWrapSpi(String name, int keySize, String supportedMode)
+ {
+ super(name, 16, keySize, supportedMode);
+ }
+
+ /**
+ * AES Key Wrapping algorithms operate on an 8-byte block; a block half the
+ * size of the AES block itself.
+ * <p>
+ * In wrapping, the number of 8-byte output blocks is ALWAYS one block longer
+ * than the input.
+ *
+ * @param inputLength the size of the plain text.
+ * @return the size in bytes of <code>n + 1</code> 8-byte blocks where
+ * <code>n</code> is the smallest number of 8-byte blocks that contain the
+ * designated number of input bytes.
+ */
+ protected int getOutputSizeForWrap(int inputLength)
+ {
+ int n = (inputLength + 7) / 8;
+ return 8 * (n + 1);
+ }
+
+ /**
+ * AES Key Wrapping algorithms operate on an 8-byte block; a block half the
+ * size of the AES block itself.
+ * <p>
+ * In unwrapping, the number of 8-byte output blocks is ALWAYS one block
+ * shorter than the input.
+ *
+ * @param inputLength the size of the cipher text.
+ * @return the size in bytes of <code>n - 1</code> 8-byte blocks where
+ * <code>n</code> is the smallest number of 8-byte blocks that contain the
+ * designated number of input bytes.
+ */
+ protected int getOutputSizeForUnwrap(int inputLength)
+ {
+ int n = (inputLength + 7) / 8;
+ return 8 * (n - 1);
+ }
+}
diff --git a/gnu/javax/crypto/jce/cipher/CipherAdapter.java b/gnu/javax/crypto/jce/cipher/CipherAdapter.java
index 9dbc40df7..b7cd755f5 100644
--- a/gnu/javax/crypto/jce/cipher/CipherAdapter.java
+++ b/gnu/javax/crypto/jce/cipher/CipherAdapter.java
@@ -343,6 +343,12 @@ class CipherAdapter
}
else if (params instanceof IvParameterSpec)
{
+ // The size of the IV must match the block size
+ if (((IvParameterSpec) params).getIV().length != cipher.defaultBlockSize())
+ {
+ throw new InvalidAlgorithmParameterException();
+ }
+
attributes.put(IMode.IV, ((IvParameterSpec) params).getIV());
blockLen = cipher.defaultBlockSize();
attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, Integer.valueOf(blockLen));
diff --git a/gnu/javax/crypto/jce/cipher/KeyWrappingAlgorithmAdapter.java b/gnu/javax/crypto/jce/cipher/KeyWrappingAlgorithmAdapter.java
new file mode 100644
index 000000000..03356a236
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/KeyWrappingAlgorithmAdapter.java
@@ -0,0 +1,423 @@
+/* KeyWrappingAlgorithmAdapter.java -- Base Adapter for Key Wrapping algorithms
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Configuration;
+import gnu.java.security.Registry;
+import gnu.javax.crypto.jce.spec.BlockCipherParameterSpec;
+import gnu.javax.crypto.kwa.IKeyWrappingAlgorithm;
+import gnu.javax.crypto.kwa.KeyUnwrappingException;
+import gnu.javax.crypto.kwa.KeyWrappingAlgorithmFactory;
+
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.CipherSpi;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * An abstract base class to facilitate implementations of JCE Adapters for
+ * symmetric key block ciphers capable of providing key-wrapping functionality.
+ */
+abstract class KeyWrappingAlgorithmAdapter
+ extends CipherSpi
+{
+ private static final Logger log = Logger.getLogger(KeyWrappingAlgorithmAdapter.class.getName());
+ /** JCE canonical name of a null-padder. */
+ private static final String NO_PADDING = "nopadding";
+ /** Concrete Key Wrapping Algorithm SPI. */
+ protected IKeyWrappingAlgorithm kwAlgorithm;
+ /** Size in bytes of the padding block to be provided by external padders. */
+ protected int kwaBlockSize;
+ /** KEK size in bytes. */
+ protected int kwaKeySize;
+ /** Name of the supported mode. */
+ protected String supportedMode;
+ /** Operational mode in which this instance was initialised. */
+ protected int opmode = -1;
+ /** Initialisation Vector if/when user wants to override default one. */
+ byte[] iv;
+
+ /**
+ * Creates a new JCE Adapter for the designated Key Wrapping Algorithm name.
+ *
+ * @param name the canonical name of the key-wrapping algorithm.
+ * @param blockSize the block size in bytes of the underlying symmetric-key
+ * block cipher algorithm.
+ * @param keySize the allowed size in bytes of the KEK bytes to initialise the
+ * underlying symmetric-key block cipher algorithm with.
+ * @param supportedMode canonical name of the block mode the underlying cipher
+ * is supporting.
+ */
+ protected KeyWrappingAlgorithmAdapter(String name, int blockSize, int keySize,
+ String supportedMode)
+ {
+ super();
+
+ this.kwAlgorithm = KeyWrappingAlgorithmFactory.getInstance(name);
+ this.kwaBlockSize = blockSize;
+ this.kwaKeySize = keySize;
+ this.supportedMode = supportedMode;
+ }
+
+ /**
+ * Wraps the encoded form of a designated {@link Key}.
+ *
+ * @param key the key-material to wrap.
+ * @return the wrapped key.
+ * @throws InvalidKeyException If the key cannot be wrapped.
+ */
+ protected byte[] engineWrap(Key key)
+ throws InvalidKeyException, IllegalBlockSizeException
+ {
+ byte[] keyMaterial = key.getEncoded();
+ byte[] result = kwAlgorithm.wrap(keyMaterial, 0, keyMaterial.length);
+ return result;
+ }
+
+ /**
+ * Unwraps a previously-wrapped key-material.
+ *
+ * @param wrappedKey the wrapped key-material to unwrap.
+ * @param wrappedKeyAlgorithm the canonical name of the algorithm, which the
+ * unwrapped key-material represents. This name is used to
+ * instantiate a concrete instance of a {@link Key} for that
+ * algorithm. For example, if the value of this parameter is
+ * <code>DSS</code> and the type (the next parameter) is
+ * {@link Cipher#PUBLIC_KEY} then an attempt to construct a concrete
+ * instance of a {@link java.security.interfaces.DSAPublicKey},
+ * using the unwrapped key material, shall be made.
+ * @param wrappedKeyType the type of wrapped key-material. MUST be one of
+ * {@link Cipher#PRIVATE_KEY}, {@link Cipher#PUBLIC_KEY}, or
+ * {@link Cipher#SECRET_KEY}.
+ * @return the unwrapped key-material as an instance of {@link Key} or one of
+ * its subclasses.
+ * @throws InvalidKeyException If the key cannot be unwrapped, or if
+ * <code>wrappedKeyType</code> is an inappropriate type for the
+ * unwrapped key.
+ * @throws NoSuchAlgorithmException If the <code>wrappedKeyAlgorithm</code>
+ * is unknown to every currently installed Security Provider.
+ */
+ protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
+ int wrappedKeyType)
+ throws InvalidKeyException, NoSuchAlgorithmException
+ {
+ byte[] keyBytes;
+ try
+ {
+ keyBytes = kwAlgorithm.unwrap(wrappedKey, 0, wrappedKey.length);
+ }
+ catch (KeyUnwrappingException x)
+ {
+ InvalidKeyException y = new InvalidKeyException("engineUnwrap()");
+ y.initCause(x);
+ throw y;
+ }
+ Key result;
+ switch (wrappedKeyType)
+ {
+ case Cipher.SECRET_KEY:
+ result = new SecretKeySpec(keyBytes, wrappedKeyAlgorithm);
+ break;
+ case Cipher.PRIVATE_KEY:
+ case Cipher.PUBLIC_KEY:
+ X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
+ KeyFactory keyFactory = KeyFactory.getInstance(wrappedKeyAlgorithm);
+ try
+ {
+ if (wrappedKeyType == Cipher.PRIVATE_KEY)
+ result = keyFactory.generatePrivate(keySpec);
+ else
+ result = keyFactory.generatePublic(keySpec);
+ }
+ catch (InvalidKeySpecException x)
+ {
+ InvalidKeyException y = new InvalidKeyException("engineUnwrap()");
+ y.initCause(x);
+ throw y;
+ }
+ break;
+ default:
+ IllegalArgumentException x = new IllegalArgumentException("Invalid 'wrappedKeyType': "
+ + wrappedKeyType);
+ InvalidKeyException y = new InvalidKeyException("engineUnwrap()");
+ y.initCause(x);
+ throw y;
+ }
+ return result;
+ }
+
+ protected int engineGetBlockSize()
+ {
+ return kwaBlockSize;
+ }
+
+ protected byte[] engineGetIV()
+ {
+ return iv == null ? null : (byte[]) iv.clone();
+ }
+
+ protected int engineGetOutputSize(int inputLength)
+ {
+ switch (opmode)
+ {
+ case Cipher.WRAP_MODE:
+ return getOutputSizeForWrap(inputLength);
+ case Cipher.UNWRAP_MODE:
+ return getOutputSizeForUnwrap(inputLength);
+ default:
+ throw new IllegalStateException();
+ }
+ }
+
+ protected AlgorithmParameters engineGetParameters()
+ {
+ BlockCipherParameterSpec spec = new BlockCipherParameterSpec(iv,
+ kwaBlockSize,
+ kwaKeySize);
+ AlgorithmParameters result = null;
+ try
+ {
+ result = AlgorithmParameters.getInstance("BlockCipherParameters");
+ result.init(spec);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ if (Configuration.DEBUG)
+ log.fine("Unable to find BlockCipherParameters. Return null");
+ }
+ catch (InvalidParameterSpecException x)
+ {
+ if (Configuration.DEBUG)
+ log.fine("Unable to initialise BlockCipherParameters. Return null");
+ }
+ return result;
+ }
+
+ protected void engineInit(int opmode, Key key, SecureRandom random)
+ throws InvalidKeyException
+ {
+ checkOpMode(opmode);
+ byte[] kekBytes = checkAndGetKekBytes(key);
+ initAlgorithm(opmode, kekBytes, null, random);
+ }
+
+ protected void engineInit(int opmode, Key key, AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidAlgorithmParameterException, InvalidKeyException
+ {
+ AlgorithmParameterSpec spec = null;
+ try
+ {
+ if (params != null)
+ spec = params.getParameterSpec(BlockCipherParameterSpec.class);
+ }
+ catch (InvalidParameterSpecException x)
+ {
+ if (Configuration.DEBUG)
+ log.fine("Unable to translate algorithm parameters into an instance "
+ + "of BlockCipherParameterSpec. Discard");
+ }
+ engineInit(opmode, key, spec, random);
+ }
+
+ protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidAlgorithmParameterException, InvalidKeyException
+ {
+ checkOpMode(opmode);
+ byte[] kekBytes = checkAndGetKekBytes(key);
+ byte[] ivBytes = null;
+ if (params instanceof BlockCipherParameterSpec)
+ ivBytes = ((BlockCipherParameterSpec) params).getIV();
+ else if (params instanceof IvParameterSpec)
+ ivBytes = ((IvParameterSpec) params).getIV();
+
+ initAlgorithm(opmode, kekBytes, ivBytes, random);
+ }
+
+ protected void engineSetMode(String mode) throws NoSuchAlgorithmException
+ {
+ if (! supportedMode.equalsIgnoreCase(mode))
+ throw new UnsupportedOperationException("Only " + supportedMode
+ + " is supported");
+ }
+
+ /**
+ * NoPadding is the only padding algorithm supported by Key Wrapping Algorithm
+ * implementations in RI.
+ */
+ protected void engineSetPadding(String padding) throws NoSuchPaddingException
+ {
+ if (! NO_PADDING.equalsIgnoreCase(padding))
+ throw new UnsupportedOperationException("Only NoPadding is supported");
+ }
+
+ protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLength)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ protected int engineUpdate(byte[] input, int inputOffset, int inputLength,
+ byte[] output, int outputOffset)
+ throws ShortBufferException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLength)
+ throws IllegalBlockSizeException, BadPaddingException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ protected int engineDoFinal(byte[] input, int inputOffset, int inputLength,
+ byte[] output, int outputOffset)
+ throws IllegalBlockSizeException, BadPaddingException, ShortBufferException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Return the minimum size in bytes of a place holder large enough to receive
+ * the cipher text resulting from a wrap method with the designated size of
+ * the plain text.
+ * <p>
+ * This default implementation ALWAYS returns the smallest multiple of the
+ * <code>kwaBlockSize</code> --passed to this method through its
+ * constructor-- greater than or equal to the designated
+ * <code>inputLength</code>.
+ *
+ * @param inputLength the size of a plain text.
+ * @return an estimate of the size, in bytes, of the place holder to receive
+ * the resulting bytes of a wrap method.
+ */
+ protected int getOutputSizeForWrap(int inputLength)
+ {
+ return kwaBlockSize * (inputLength + kwaBlockSize - 1) / kwaBlockSize;
+ }
+
+ /**
+ * Return the minimum size in bytes of a place holder large enough to receive
+ * the plain text resulting from an unwrap method with the designated size of
+ * the cipher text.
+ * <p>
+ * This default implementation ALWAYS returns the smallest multiple of the
+ * <code>paddingBlockSize</code> --passed to this method through its
+ * constructor-- greater than or equal to the designated
+ * <code>inputLength</code>.
+ *
+ * @param inputLength the size of a cipher text.
+ * @return an estimate of the size, in bytes, of the place holder to receive
+ * the resulting bytes of an uwrap method.
+ */
+ protected int getOutputSizeForUnwrap(int inputLength)
+ {
+ return kwaBlockSize * (inputLength + kwaBlockSize - 1) / kwaBlockSize;
+ }
+
+ private void checkOpMode(int opmode)
+ {
+ switch (opmode)
+ {
+ case Cipher.WRAP_MODE:
+ case Cipher.UNWRAP_MODE:
+ return;
+ }
+ throw new IllegalArgumentException("Unsupported operational mode: " + opmode);
+ }
+
+ /**
+ * Returns the key bytes, iff it was in RAW format.
+ *
+ * @param key the opaque JCE secret key to use as the KEK.
+ * @return the bytes of the encoded form of the designated kek, iff it was in
+ * RAW format.
+ * @throws InvalidKeyException if the designated key is not in the RAW format.
+ */
+ private byte[] checkAndGetKekBytes(Key key) throws InvalidKeyException
+ {
+ if (! Registry.RAW_ENCODING_SHORT_NAME.equalsIgnoreCase(key.getFormat()))
+ throw new InvalidKeyException("Only RAW key format is supported");
+ byte[] result = key.getEncoded();
+ int kekSize = result.length;
+ if (kekSize != kwaKeySize)
+ throw new InvalidKeyException("Invalid key material size. Expected "
+ + kwaKeySize + " but found " + kekSize);
+ return result;
+ }
+
+ private void initAlgorithm(int opmode, byte[] kek, byte[] ivBytes,
+ SecureRandom rnd)
+ throws InvalidKeyException
+ {
+ this.opmode = opmode;
+ Map attributes = new HashMap();
+ attributes.put(IKeyWrappingAlgorithm.KEY_ENCRYPTION_KEY_MATERIAL, kek);
+ if (ivBytes != null)
+ {
+ this.iv = (byte[]) ivBytes.clone();
+ attributes.put(IKeyWrappingAlgorithm.INITIAL_VALUE, this.iv);
+ }
+ else
+ this.iv = null;
+ if (rnd != null)
+ attributes.put(IKeyWrappingAlgorithm.SOURCE_OF_RANDOMNESS, rnd);
+
+ kwAlgorithm.init(attributes);
+ }
+}
diff --git a/gnu/javax/crypto/jce/cipher/TripleDESKeyWrapSpi.java b/gnu/javax/crypto/jce/cipher/TripleDESKeyWrapSpi.java
new file mode 100644
index 000000000..55087755e
--- /dev/null
+++ b/gnu/javax/crypto/jce/cipher/TripleDESKeyWrapSpi.java
@@ -0,0 +1,54 @@
+/* TripleDESKeyWrapSpi.java -- DES-EDE Key Wrapping Algorithm JCE Adapter
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.jce.cipher;
+
+import gnu.java.security.Registry;
+
+/**
+ * The JCE Cipher Adapter implementation over the GNU TripleDES Key Wrapping
+ * Algorithm.
+ */
+public final class TripleDESKeyWrapSpi
+ extends KeyWrappingAlgorithmAdapter
+{
+ public TripleDESKeyWrapSpi()
+ {
+ super(Registry.TRIPLEDES_KWA, 8, 192 / 8, Registry.CBC_MODE);
+ }
+}
diff --git a/gnu/javax/crypto/jce/params/BlockCipherParameters.java b/gnu/javax/crypto/jce/params/BlockCipherParameters.java
index 4ed3015fd..a85c96223 100644
--- a/gnu/javax/crypto/jce/params/BlockCipherParameters.java
+++ b/gnu/javax/crypto/jce/params/BlockCipherParameters.java
@@ -49,6 +49,8 @@ import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.util.logging.Logger;
+import javax.crypto.spec.IvParameterSpec;
+
/**
* An implementation of algorithm parameters for the GNU block ciphers. This
* encompasses the cipher's block size, its key size, and an optional
@@ -132,6 +134,11 @@ public class BlockCipherParameters
{
if (c.isInstance(cipherSpec))
return cipherSpec;
+ if (IvParameterSpec.class.isAssignableFrom(c))
+ {
+ IvParameterSpec result = new IvParameterSpec(cipherSpec.getIV());
+ return result;
+ }
throw new InvalidParameterSpecException();
}
diff --git a/gnu/javax/crypto/key/dh/GnuDHKey.java b/gnu/javax/crypto/key/dh/GnuDHKey.java
index e37642f0a..1066830c3 100644
--- a/gnu/javax/crypto/key/dh/GnuDHKey.java
+++ b/gnu/javax/crypto/key/dh/GnuDHKey.java
@@ -38,11 +38,12 @@ exception statement from your version. */
package gnu.javax.crypto.key.dh;
-import gnu.classpath.SystemProperties;
import gnu.java.security.Registry;
+import gnu.java.security.action.GetPropertyAction;
import gnu.java.security.util.FormatUtil;
import java.math.BigInteger;
+import java.security.AccessController;
import java.security.Key;
import javax.crypto.interfaces.DHKey;
@@ -154,7 +155,8 @@ public abstract class GnuDHKey
{
if (str == null)
{
- String ls = SystemProperties.getProperty("line.separator");
+ String ls = (String) AccessController.doPrivileged
+ (new GetPropertyAction("line.separator"));
StringBuilder sb = new StringBuilder(ls)
.append("defaultFormat=").append(defaultFormat).append(",").append(ls);
if (q == null)
diff --git a/gnu/javax/crypto/key/dh/GnuDHPrivateKey.java b/gnu/javax/crypto/key/dh/GnuDHPrivateKey.java
index 7321102de..d8150dcdf 100644
--- a/gnu/javax/crypto/key/dh/GnuDHPrivateKey.java
+++ b/gnu/javax/crypto/key/dh/GnuDHPrivateKey.java
@@ -38,12 +38,13 @@ exception statement from your version. */
package gnu.javax.crypto.key.dh;
-import gnu.classpath.SystemProperties;
import gnu.java.security.Configuration;
import gnu.java.security.Registry;
+import gnu.java.security.action.GetPropertyAction;
import gnu.java.security.key.IKeyPairCodec;
import java.math.BigInteger;
+import java.security.AccessController;
import javax.crypto.interfaces.DHPrivateKey;
@@ -185,7 +186,8 @@ public class GnuDHPrivateKey
{
if (str == null)
{
- String ls = SystemProperties.getProperty("line.separator");
+ String ls = (String) AccessController.doPrivileged
+ (new GetPropertyAction("line.separator"));
str = new StringBuilder(this.getClass().getName()).append("(")
.append(super.toString()).append(",").append(ls)
.append("x=0x").append(Configuration.DEBUG ? x.toString(16)
diff --git a/gnu/javax/crypto/key/dh/GnuDHPublicKey.java b/gnu/javax/crypto/key/dh/GnuDHPublicKey.java
index 5acc45299..5fb31f383 100644
--- a/gnu/javax/crypto/key/dh/GnuDHPublicKey.java
+++ b/gnu/javax/crypto/key/dh/GnuDHPublicKey.java
@@ -38,11 +38,12 @@ exception statement from your version. */
package gnu.javax.crypto.key.dh;
-import gnu.classpath.SystemProperties;
import gnu.java.security.Registry;
+import gnu.java.security.action.GetPropertyAction;
import gnu.java.security.key.IKeyPairCodec;
import java.math.BigInteger;
+import java.security.AccessController;
import javax.crypto.interfaces.DHPublicKey;
@@ -182,7 +183,8 @@ public class GnuDHPublicKey
{
if (str == null)
{
- String ls = SystemProperties.getProperty("line.separator");
+ String ls = (String) AccessController.doPrivileged
+ (new GetPropertyAction("line.separator"));
str = new StringBuilder(this.getClass().getName()).append("(")
.append(super.toString()).append(",").append(ls)
.append("y=0x").append(y.toString(16)).append(ls)
diff --git a/gnu/javax/crypto/kwa/AESKeyWrap.java b/gnu/javax/crypto/kwa/AESKeyWrap.java
new file mode 100644
index 000000000..bb86c5477
--- /dev/null
+++ b/gnu/javax/crypto/kwa/AESKeyWrap.java
@@ -0,0 +1,168 @@
+/* AESWrap.java -- An implementation of RFC-3394 AES Key Wrap Algorithm
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.kwa;
+
+import gnu.java.security.Registry;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.cipher.Rijndael;
+
+import java.security.InvalidKeyException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The GNU implementation of the AES Key Wrap Algorithm as described in [1].
+ * <p>
+ * References:
+ * <ol>
+ * <li><a href="http://csrc.nist.gov/encryption/kms/key-wrap.pdf"></a>.</li>
+ * <li><a href="http://www.rfc-archive.org/getrfc.php?rfc=3394">Advanced
+ * Encryption Standard (AES) Key Wrap Algorithm</a>.</li>
+ * <li><a href="http://www.w3.org/TR/xmlenc-core/">XML Encryption Syntax and
+ * Processing</a>.</li>
+ * </ol>
+ */
+public class AESKeyWrap
+ extends BaseKeyWrappingAlgorithm
+{
+ private static final byte[] DEFAULT_IV = new byte[] {
+ (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6,
+ (byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6 };
+
+ private Rijndael aes;
+ private byte[] iv;
+
+ public AESKeyWrap()
+ {
+ super(Registry.AES_KWA);
+
+ aes = new Rijndael();
+ }
+
+ protected void engineInit(Map attributes) throws InvalidKeyException
+ {
+ Map cipherAttributes = new HashMap();
+ cipherAttributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, Integer.valueOf(16));
+ cipherAttributes.put(IBlockCipher.KEY_MATERIAL,
+ attributes.get(KEY_ENCRYPTION_KEY_MATERIAL));
+ aes.reset();
+ aes.init(cipherAttributes);
+ byte[] initialValue = (byte[]) attributes.get(INITIAL_VALUE);
+ iv = initialValue == null ? DEFAULT_IV : (byte[]) initialValue.clone();
+ }
+
+ protected byte[] engineWrap(byte[] in, int inOffset, int length)
+ {
+ // TODO: handle input length which is not a multiple of 8 as suggested by
+ // section 2.2.3.2 of RFC-3394
+ if (length % 8 != 0)
+ throw new IllegalArgumentException("Input length MUST be a multiple of 8");
+ int n = length / 8;
+ // output is always one block larger than input
+ byte[] result = new byte[length + 8];
+
+ // 1. init variables: we'll use out buffer for our work buffer;
+ // A will be the first block in out, while R will be the rest
+ System.arraycopy(iv, 0, result, 0, 8);
+ System.arraycopy(in, inOffset, result, 8, length);
+ byte[] B = new byte[2 * 8];
+ // 2. compute intermediate values
+ long t;
+ for (int j = 0; j < 6; j++)
+ for (int i = 1; i <= n; i++)
+ {
+ System.arraycopy(result, 0, B, 0, 8);
+ System.arraycopy(result, i * 8, B, 8, 8);
+ aes.encryptBlock(B, 0, B, 0);
+ t = (n * j) + i;
+ result[0] = (byte)(B[0] ^ (t >>> 56));
+ result[1] = (byte)(B[1] ^ (t >>> 48));
+ result[2] = (byte)(B[2] ^ (t >>> 40));
+ result[3] = (byte)(B[3] ^ (t >>> 32));
+ result[4] = (byte)(B[4] ^ (t >>> 24));
+ result[5] = (byte)(B[5] ^ (t >>> 16));
+ result[6] = (byte)(B[6] ^ (t >>> 8));
+ result[7] = (byte)(B[7] ^ t );
+ System.arraycopy(B, 8, result, i * 8, 8);
+ }
+ return result;
+ }
+
+ protected byte[] engineUnwrap(byte[] in, int inOffset, int length)
+ throws KeyUnwrappingException
+ {
+ // TODO: handle input length which is not a multiple of 8 as suggested by
+ // section 2.2.3.2 of RFC-3394
+ if (length % 8 != 0)
+ throw new IllegalArgumentException("Input length MUST be a multiple of 8");
+ // output is always one block shorter than input
+ byte[] result = new byte[length - 8];
+
+ // 1. init variables: we'll use out buffer for our R work buffer
+ byte[] A = new byte[8];
+ System.arraycopy(in, inOffset, A, 0, 8);
+ System.arraycopy(in, inOffset + 8, result, 0, result.length);
+ byte[] B = new byte[2 * 8];
+ // 2. compute intermediate values
+ int n = length / 8 - 1;
+ long t;
+ for (int j = 5; j >= 0; j--)
+ for (int i = n; i >= 1; i--)
+ {
+ t = (n * j) + i;
+ B[0] = (byte)(A[0] ^ (t >>> 56));
+ B[1] = (byte)(A[1] ^ (t >>> 48));
+ B[2] = (byte)(A[2] ^ (t >>> 40));
+ B[3] = (byte)(A[3] ^ (t >>> 32));
+ B[4] = (byte)(A[4] ^ (t >>> 24));
+ B[5] = (byte)(A[5] ^ (t >>> 16));
+ B[6] = (byte)(A[6] ^ (t >>> 8));
+ B[7] = (byte)(A[7] ^ t );
+ System.arraycopy(result, (i - 1) * 8, B, 8, 8);
+ aes.decryptBlock(B, 0, B, 0);
+ System.arraycopy(B, 0, A, 0, 8);
+ System.arraycopy(B, 8, result, (i - 1) * 8, 8);
+ }
+ if (! Arrays.equals(A, iv))
+ throw new KeyUnwrappingException();
+
+ return result;
+ }
+}
diff --git a/gnu/javax/crypto/kwa/BaseKeyWrappingAlgorithm.java b/gnu/javax/crypto/kwa/BaseKeyWrappingAlgorithm.java
new file mode 100644
index 000000000..206e01d13
--- /dev/null
+++ b/gnu/javax/crypto/kwa/BaseKeyWrappingAlgorithm.java
@@ -0,0 +1,145 @@
+/* BaseKeyWrappingAlgorithm.java -- FIXME: briefly describe file purpose
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.kwa;
+
+import gnu.java.security.util.PRNG;
+
+import java.security.InvalidKeyException;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.crypto.ShortBufferException;
+
+/**
+ * A base class to facilitate implementation of concrete Key Wrapping
+ * Algorithms.
+ */
+public abstract class BaseKeyWrappingAlgorithm
+ implements IKeyWrappingAlgorithm
+{
+ /** The canonical name of the key wrapping algorithm. */
+ protected String name;
+ /** A source of randomness if/when needed by concrete implementations. */
+ private PRNG prng;
+
+ /**
+ * Protected constructor.
+ *
+ * @param name the key wrapping algorithm canonical name.
+ */
+ protected BaseKeyWrappingAlgorithm(String name)
+ {
+ super();
+ }
+
+ public String name()
+ {
+ return this.name;
+ }
+
+ public void init(Map attributes) throws InvalidKeyException
+ {
+ if (attributes == null)
+ attributes = Collections.EMPTY_MAP;
+
+ engineInit(attributes);
+ }
+
+ public int wrap(byte[] in, int inOffset, int length, byte[] out, int outOffset)
+ throws ShortBufferException
+ {
+ if (outOffset < 0)
+ throw new IllegalArgumentException("Output offset MUST NOT be negative");
+ byte[] result = wrap(in, inOffset, length);
+ if (outOffset + result.length > out.length)
+ throw new ShortBufferException();
+ System.arraycopy(result, 0, out, outOffset, result.length);
+ return result.length;
+ }
+
+ public byte[] wrap(byte[] in, int inOffset, int length)
+ {
+ if (inOffset < 0)
+ throw new IllegalArgumentException("Input offset MUST NOT be negative");
+ if (length < 0)
+ throw new IllegalArgumentException("Input length MUST NOT be negative");
+
+ return engineWrap(in, inOffset, length);
+ }
+
+ public int unwrap(byte[] in, int inOffset, int length,
+ byte[] out, int outOffset)
+ throws ShortBufferException, KeyUnwrappingException
+ {
+ if (outOffset < 0)
+ throw new IllegalArgumentException("Output offset MUST NOT be negative");
+ byte[] result = engineUnwrap(in, inOffset, length);
+ if (outOffset + result.length > out.length)
+ throw new ShortBufferException();
+ System.arraycopy(result, 0, out, outOffset, result.length);
+ return result.length;
+ }
+
+ public byte[] unwrap(byte[] in, int inOffset, int length)
+ throws KeyUnwrappingException
+ {
+ if (inOffset < 0)
+ throw new IllegalArgumentException("Input offset MUST NOT be negative");
+ if (length < 0)
+ throw new IllegalArgumentException("Input length MUST NOT be negative");
+
+ return engineUnwrap(in, inOffset, length);
+ }
+
+ protected abstract void engineInit(Map attributes) throws InvalidKeyException;
+
+ protected abstract byte[] engineWrap(byte[] in, int inOffset, int length);
+
+ protected abstract byte[] engineUnwrap(byte[] in, int inOffset, int length)
+ throws KeyUnwrappingException;
+
+ /** @return a strong pseudo-random number generator if/when needed. */
+ protected PRNG getDefaultPRNG()
+ {
+ if (prng == null)
+ prng = PRNG.getInstance();
+
+ return prng;
+ }
+}
diff --git a/gnu/javax/crypto/kwa/IKeyWrappingAlgorithm.java b/gnu/javax/crypto/kwa/IKeyWrappingAlgorithm.java
new file mode 100644
index 000000000..d9c2bed14
--- /dev/null
+++ b/gnu/javax/crypto/kwa/IKeyWrappingAlgorithm.java
@@ -0,0 +1,160 @@
+/* IKeyWrappingAlgorithm.java -- FIXME: briefly describe file purpose
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.kwa;
+
+import java.security.InvalidKeyException;
+import java.security.SecureRandom;
+import java.util.Map;
+
+import javax.crypto.ShortBufferException;
+
+/**
+ * Constants and visible methods available to all GNU Key Wrapping Algorithm
+ * implementations.
+ */
+public interface IKeyWrappingAlgorithm
+{
+ /**
+ * Name of the property, in the attributes map, that references the Key
+ * Wrapping Algorithm KEK (Key Encryption Key) material. The object referenced
+ * by this property is a byte array containing the keying material for the
+ * underlying block cipher.
+ */
+ String KEY_ENCRYPTION_KEY_MATERIAL = "gnu.crypto.kwa.kek";
+ /**
+ * Name of the property, in the attributes map, that references the Initial
+ * Value (IV) material. The object referenced by this property is a byte array
+ * containing the initial integrity check register value.
+ */
+ String INITIAL_VALUE = "gnu.crypto.kwa.iv";
+ /**
+ * Property name of an optional {@link SecureRandom} instance to use. The
+ * default is to use a {@link gnu.java.security.util.PRNG} instance.
+ */
+ String SOURCE_OF_RANDOMNESS = "gnu.crypto.kwa.prng";
+
+ /**
+ * Returns the canonical name of this Key Wrapping Algorithm.
+ *
+ * @return the canonical name of this Key Wrapping Algorithm.
+ */
+ String name();
+
+ /**
+ * Initializes this instance with the designated algorithm specific
+ * attributes.
+ *
+ * @param attributes a map of name-to-value pairs the Key Wrapping Algorithm
+ * must use for its setup.
+ * @throws InvalidKeyException if an exception is encountered while seting up
+ * the Key Wrapping Algorithm keying material (KEK).
+ */
+ void init(Map attributes) throws InvalidKeyException;
+
+ /**
+ * Wraps the designated plain text bytes.
+ *
+ * @param in the input byte array containing the plain text.
+ * @param inOffset the offset into <code>in</code> where the first byte of
+ * the plain text (key material) to wrap is located.
+ * @param length the number of bytes to wrap.
+ * @param out the output byte array where the wrapped key material will be
+ * stored.
+ * @param outOffset the offset into <code>out</code> of the first wrapped
+ * byte.
+ * @return the number of bytes of the wrapped key material; i.e. the length,
+ * in <code>out</code>, starting from <code>outOffset</code>
+ * where the cipher text (wrapped key material) are stored.
+ * @throws ShortBufferException if the output buffer is not long enough to
+ * accomodate the number of bytes resulting from wrapping the plain
+ * text.
+ */
+ int wrap(byte[] in, int inOffset, int length, byte[] out, int outOffset)
+ throws ShortBufferException;
+
+ /**
+ * Wraps the designated plain text bytes.
+ *
+ * @param in the input byte array containing the plain text.
+ * @param inOffset the offset into <code>in</code> where the first byte of
+ * the plain text (key material) to wrap is located.
+ * @param length the number of bytes to wrap.
+ * @return a newly allocated byte array containing the cipher text.
+ */
+ byte[] wrap(byte[] in, int inOffset, int length);
+
+ /**
+ * Unwraps the designated cipher text bytes.
+ *
+ * @param in the input byte array containing the cipher text.
+ * @param inOffset the offset into <code>in</code> where the first byte of
+ * the cipher text (already wrapped key material) to unwrap is
+ * located.
+ * @param length the number of bytes to unwrap.
+ * @param out the output byte array where the unwrapped key material will be
+ * stored.
+ * @param outOffset the offset into <code>out</code> of the first unwrapped
+ * byte.
+ * @return the number of bytes of the unwrapped key material; i.e. the length,
+ * in <code>out</code>, starting from <code>outOffset</code>
+ * where the plain text (unwrapped key material) are stored.
+ * @throws ShortBufferException if the output buffer is not long enough to
+ * accomodate the number of bytes resulting from unwrapping the
+ * cipher text.
+ * @throws KeyUnwrappingException if after unwrapping the cipher text, the
+ * bytes at the begining did not match the initial value.
+ */
+ int unwrap(byte[] in, int inOffset, int length, byte[] out, int outOffset)
+ throws ShortBufferException, KeyUnwrappingException;
+
+ /**
+ * Unwraps the designated cipher text bytes.
+ *
+ * @param in the input byte array containing the cipher text.
+ * @param inOffset the offset into <code>in</code> where the first byte of
+ * the cipher text (already wrapped key material) to unwrap is
+ * located.
+ * @param length the number of bytes to unwrap.
+ * @return a newly allocated byte array containing the plain text.
+ * @throws KeyUnwrappingException if after unwrapping the cipher text, the
+ * bytes at the begining did not match the initial value.
+ */
+ byte[] unwrap(byte[] in, int inOffset, int length)
+ throws KeyUnwrappingException;
+}
diff --git a/gnu/javax/crypto/kwa/KeyUnwrappingException.java b/gnu/javax/crypto/kwa/KeyUnwrappingException.java
new file mode 100644
index 000000000..54b4aff0a
--- /dev/null
+++ b/gnu/javax/crypto/kwa/KeyUnwrappingException.java
@@ -0,0 +1,67 @@
+/* KeyUnwrappingException.java -- FIXME: briefly describe file purpose
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.kwa;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * A checked security exception to denote an unexpected problem while unwrapping
+ * key material with a Key Wrapping Algorithm.
+ */
+public class KeyUnwrappingException
+ extends GeneralSecurityException
+{
+ /**
+ * Create a new instance with no descriptive error message.
+ */
+ public KeyUnwrappingException()
+ {
+ super();
+ }
+
+ /**
+ * Create a new instance with a descriptive error message.
+ *
+ * @param msg the descriptive error message
+ */
+ public KeyUnwrappingException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/gnu/javax/crypto/kwa/KeyWrappingAlgorithmFactory.java b/gnu/javax/crypto/kwa/KeyWrappingAlgorithmFactory.java
new file mode 100644
index 000000000..6f6cd1219
--- /dev/null
+++ b/gnu/javax/crypto/kwa/KeyWrappingAlgorithmFactory.java
@@ -0,0 +1,110 @@
+/* KeyWrappingAlgorithmFactory.java -- FIXME: briefly describe file purpose
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.kwa;
+
+import gnu.java.security.Registry;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A Factory class for the Key Wrapping Algorithm implementations.
+ */
+public class KeyWrappingAlgorithmFactory
+{
+ /** Names of Key Wrapping Algorihms cached for speed. */
+ private static Set names;
+
+ /** Trivial constructor to enforce Singleton pattern. */
+ private KeyWrappingAlgorithmFactory()
+ {
+ super();
+ }
+
+ /**
+ * Returns an instance of a key-wrapping algorithm given its name.
+ *
+ * @param name the case-insensitive name of the key-wrapping algorithm.
+ * @return an instance of the designated key-wrapping algorithm, or
+ * <code>null</code> if none was found.
+ * @exception InternalError if the implementation does not pass its self-test.
+ */
+ public static final IKeyWrappingAlgorithm getInstance(String name)
+ {
+ if (name == null)
+ return null;
+ name = name.trim();
+ IKeyWrappingAlgorithm result = null;
+ if (name.equalsIgnoreCase(Registry.AES_KWA)
+ || name.equalsIgnoreCase(Registry.AES128_KWA)
+ || name.equalsIgnoreCase(Registry.AES192_KWA)
+ || name.equalsIgnoreCase(Registry.AES256_KWA)
+ || name.equalsIgnoreCase(Registry.RIJNDAEL_KWA))
+ result = new AESKeyWrap();
+ else if (name.equalsIgnoreCase(Registry.TRIPLEDES_KWA)
+ || name.equalsIgnoreCase(Registry.DESEDE_KWA))
+ result = new TripleDESKeyWrap();
+
+ return result;
+ }
+
+ /**
+ * Returns a {@link Set} of key wrapping algorithm names supported by this
+ * <i>Factory</i>.
+ *
+ * @return a {@link Set} of key wrapping algorithm names (Strings).
+ */
+ public static synchronized final Set getNames()
+ {
+ if (names == null)
+ {
+ HashSet hs = new HashSet();
+ hs.add(Registry.AES_KWA);
+ hs.add(Registry.AES128_KWA);
+ hs.add(Registry.AES192_KWA);
+ hs.add(Registry.AES256_KWA);
+ hs.add(Registry.RIJNDAEL_KWA);
+ hs.add(Registry.TRIPLEDES_KWA);
+ hs.add(Registry.DESEDE_KWA);
+ names = Collections.unmodifiableSet(hs);
+ }
+ return names;
+ }
+}
diff --git a/gnu/javax/crypto/kwa/TripleDESKeyWrap.java b/gnu/javax/crypto/kwa/TripleDESKeyWrap.java
new file mode 100644
index 000000000..71562bd75
--- /dev/null
+++ b/gnu/javax/crypto/kwa/TripleDESKeyWrap.java
@@ -0,0 +1,292 @@
+/* TripleDESKeyWrap.java -- FIXME: briefly describe file purpose
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.kwa;
+
+import gnu.java.security.Registry;
+import gnu.java.security.hash.Sha160;
+import gnu.javax.crypto.assembly.Assembly;
+import gnu.javax.crypto.assembly.Cascade;
+import gnu.javax.crypto.assembly.Direction;
+import gnu.javax.crypto.assembly.Stage;
+import gnu.javax.crypto.assembly.Transformer;
+import gnu.javax.crypto.assembly.TransformerException;
+import gnu.javax.crypto.cipher.IBlockCipher;
+import gnu.javax.crypto.cipher.TripleDES;
+import gnu.javax.crypto.mode.IMode;
+import gnu.javax.crypto.mode.ModeFactory;
+
+import java.security.InvalidKeyException;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The GNU implementation of the Triple DES Key Wrap Algorithm as described in
+ * [1].
+ * <p>
+ * <b>IMPORTANT</b>: This class is NOT thread safe.
+ * <p>
+ * References:
+ * <ol>
+ * <li><a href="http://www.rfc-archive.org/getrfc.php?rfc=3217">Triple-DES and
+ * RC2 Key Wrapping</a>.</li>
+ * <li><a href="http://www.w3.org/TR/xmlenc-core/">XML Encryption Syntax and
+ * Processing</a>.</li>
+ * </ol>
+ */
+public class TripleDESKeyWrap
+ extends BaseKeyWrappingAlgorithm
+{
+ private static final byte[] DEFAULT_IV = new byte[] {
+ (byte) 0x4A, (byte) 0xDD, (byte) 0xA2, (byte) 0x2C,
+ (byte) 0x79, (byte) 0xE8, (byte) 0x21, (byte) 0x05 };
+
+ private Assembly asm;
+ private HashMap asmAttributes = new HashMap();
+ private HashMap modeAttributes = new HashMap();
+ private Sha160 sha = new Sha160();
+ private SecureRandom rnd;
+
+ public TripleDESKeyWrap()
+ {
+ super(Registry.TRIPLEDES_KWA);
+ }
+
+ protected void engineInit(Map attributes) throws InvalidKeyException
+ {
+ rnd = (SecureRandom) attributes.get(IKeyWrappingAlgorithm.SOURCE_OF_RANDOMNESS);
+ IMode des3CBC = ModeFactory.getInstance(Registry.CBC_MODE, new TripleDES(), 8);
+ Stage des3CBCStage = Stage.getInstance(des3CBC, Direction.FORWARD);
+ Cascade cascade = new Cascade();
+ Object modeNdx = cascade.append(des3CBCStage);
+
+ asmAttributes.put(modeNdx, modeAttributes);
+
+ asm = new Assembly();
+ asm.addPreTransformer(Transformer.getCascadeTransformer(cascade));
+
+ modeAttributes.put(IBlockCipher.KEY_MATERIAL,
+ attributes.get(KEY_ENCRYPTION_KEY_MATERIAL));
+ asmAttributes.put(Assembly.DIRECTION, Direction.FORWARD);
+ }
+
+ protected byte[] engineWrap(byte[] in, int inOffset, int length)
+ {
+ // The same key wrap algorithm is used for both Two-key Triple-DES and
+ // Three-key Triple-DES keys. When a Two-key Triple-DES key is to be
+ // wrapped, a third DES key with the same value as the first DES key is
+ // created. Thus, all wrapped Triple-DES keys include three DES keys.
+ if (length != 16 && length != 24)
+ throw new IllegalArgumentException("Only 2- and 3-key Triple DES keys are alowed");
+
+ byte[] CEK = new byte[24];
+ if (length == 16)
+ {
+ System.arraycopy(in, inOffset, CEK, 0, 16);
+ System.arraycopy(in, inOffset, CEK, 16, 8);
+ }
+ else
+ System.arraycopy(in, inOffset, CEK, 0, 24);
+
+ // TODO: check for the following:
+ // However, a Two-key Triple-DES key MUST NOT be used to wrap a Three-
+ // key Triple-DES key that is comprised of three unique DES keys.
+
+ // 1. Set odd parity for each of the DES key octets comprising the
+ // Three-Key Triple-DES key that is to be wrapped, call the result
+ // CEK.
+ TripleDES.adjustParity(CEK, 0);
+
+ // 2. Compute an 8 octet key checksum value on CEK as described above in
+ // Section 2, call the result ICV.
+ sha.update(CEK);
+ byte[] hash = sha.digest();
+ byte[] ICV = new byte[8];
+ System.arraycopy(hash, 0, ICV, 0, 8);
+
+ // 3. Let CEKICV = CEK || ICV.
+ byte[] CEKICV = new byte[CEK.length + ICV.length];
+ System.arraycopy(CEK, 0, CEKICV, 0, CEK.length);
+ System.arraycopy(ICV, 0, CEKICV, CEK.length, ICV.length);
+
+ // 4. Generate 8 octets at random, call the result IV.
+ byte[] IV = new byte[8];
+ nextRandomBytes(IV);
+
+ // 5. Encrypt CEKICV in CBC mode using the key-encryption key. Use the
+ // random value generated in the previous step as the initialization
+ // vector (IV). Call the ciphertext TEMP1.
+ modeAttributes.put(IMode.IV, IV);
+ asmAttributes.put(Assembly.DIRECTION, Direction.FORWARD);
+ byte[] TEMP1;
+ try
+ {
+ asm.init(asmAttributes);
+ TEMP1 = asm.lastUpdate(CEKICV);
+ }
+ catch (TransformerException x)
+ {
+ throw new RuntimeException(x);
+ }
+
+ // 6. Let TEMP2 = IV || TEMP1.
+ byte[] TEMP2 = new byte[IV.length + TEMP1.length];
+ System.arraycopy(IV, 0, TEMP2, 0, IV.length);
+ System.arraycopy(TEMP1, 0, TEMP2, IV.length, TEMP1.length);
+
+ // 7. Reverse the order of the octets in TEMP2. That is, the most
+ // significant (first) octet is swapped with the least significant
+ // (last) octet, and so on. Call the result TEMP3.
+ byte[] TEMP3 = new byte[TEMP2.length];
+ for (int i = 0, j = TEMP2.length - 1; i < TEMP2.length; i++, j--)
+ TEMP3[j] = TEMP2[i];
+
+ // 8. Encrypt TEMP3 in CBC mode using the key-encryption key. Use an
+ // initialization vector (IV) of 0x4adda22c79e82105. The ciphertext
+ // is 40 octets long.
+ modeAttributes.put(IMode.IV, DEFAULT_IV);
+ asmAttributes.put(Assembly.DIRECTION, Direction.FORWARD);
+ byte[] result;
+ try
+ {
+ asm.init(asmAttributes);
+ result = asm.lastUpdate(TEMP3);
+ }
+ catch (TransformerException x)
+ {
+ throw new RuntimeException(x);
+ }
+ return result;
+ }
+
+ protected byte[] engineUnwrap(byte[] in, int inOffset, int length)
+ throws KeyUnwrappingException
+ {
+ // 1. If the wrapped key is not 40 octets, then error.
+ if (length != 40)
+ throw new IllegalArgumentException("length MUST be 40");
+
+ // 2. Decrypt the wrapped key in CBC mode using the key-encryption key.
+ // Use an initialization vector (IV) of 0x4adda22c79e82105. Call the
+ // output TEMP3.
+ modeAttributes.put(IMode.IV, DEFAULT_IV);
+ asmAttributes.put(Assembly.DIRECTION, Direction.REVERSED);
+ byte[] TEMP3;
+ try
+ {
+ asm.init(asmAttributes);
+ TEMP3 = asm.lastUpdate(in, inOffset, 40);
+ }
+ catch (TransformerException x)
+ {
+ throw new RuntimeException(x);
+ }
+
+ // 3. Reverse the order of the octets in TEMP3. That is, the most
+ // significant (first) octet is swapped with the least significant
+ // (last) octet, and so on. Call the result TEMP2.
+ byte[] TEMP2 = new byte[40];
+ for (int i = 0, j = 40 - 1; i < 40; i++, j--)
+ TEMP2[j] = TEMP3[i];
+
+ // 4. Decompose TEMP2 into IV and TEMP1. IV is the most significant
+ // (first) 8 octets, and TEMP1 is the least significant (last) 32
+ // octets.
+ byte[] IV = new byte[8];
+ byte[] TEMP1 = new byte[32];
+ System.arraycopy(TEMP2, 0, IV, 0, 8);
+ System.arraycopy(TEMP2, 8, TEMP1, 0, 32);
+
+ // 5. Decrypt TEMP1 in CBC mode using the key-encryption key. Use the
+ // IV value from the previous step as the initialization vector.
+ // Call the ciphertext CEKICV.
+ modeAttributes.put(IMode.IV, IV);
+ asmAttributes.put(Assembly.DIRECTION, Direction.REVERSED);
+ byte[] CEKICV;
+ try
+ {
+ asm.init(asmAttributes);
+ CEKICV = asm.lastUpdate(TEMP1, 0, 32);
+ }
+ catch (TransformerException x)
+ {
+ throw new RuntimeException(x);
+ }
+
+ // 6. Decompose CEKICV into CEK and ICV. CEK is the most significant
+ // (first) 24 octets, and ICV is the least significant (last) 8
+ // octets.
+ byte[] CEK = new byte[24];
+ byte[] ICV = new byte[8];
+ System.arraycopy(CEKICV, 0, CEK, 0, 24);
+ System.arraycopy(CEKICV, 24, ICV, 0, 8);
+
+ // 7. Compute an 8 octet key checksum value on CEK as described above in
+ // Section 2. If the computed key checksum value does not match the
+ // decrypted key checksum value, ICV, then error.
+ sha.update(CEK);
+ byte[] hash = sha.digest();
+ byte[] computedICV = new byte[8];
+ System.arraycopy(hash, 0, computedICV, 0, 8);
+ if (! Arrays.equals(ICV, computedICV))
+ throw new KeyUnwrappingException("ICV and computed ICV MUST match");
+
+ // 8. Check for odd parity each of the DES key octets comprising CEK.
+ // If parity is incorrect, then error.
+ if (! TripleDES.isParityAdjusted(CEK, 0))
+ throw new KeyUnwrappingException("Triple-DES key parity MUST be adjusted");
+
+ // 9. Use CEK as a Triple-DES key.
+ return CEK;
+ }
+
+ /**
+ * Fills the designated byte array with random data.
+ *
+ * @param buffer the byte array to fill with random data.
+ */
+ private void nextRandomBytes(byte[] buffer)
+ {
+ if (rnd != null)
+ rnd.nextBytes(buffer);
+ else
+ getDefaultPRNG().nextBytes(buffer);
+ }
+}
diff --git a/gnu/javax/crypto/pad/BasePad.java b/gnu/javax/crypto/pad/BasePad.java
index 29ba159c6..8b475d2d8 100644
--- a/gnu/javax/crypto/pad/BasePad.java
+++ b/gnu/javax/crypto/pad/BasePad.java
@@ -40,6 +40,7 @@ package gnu.javax.crypto.pad;
import gnu.java.security.Configuration;
+import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -80,6 +81,28 @@ public abstract class BasePad
setup();
}
+ /**
+ * Initialises the algorithm with designated attributes. Names, valid and/or
+ * recognisable by all concrete implementations are described in {@link IPad}
+ * class documentation. Other algorithm-specific attributes MUST be documented
+ * in the implementation class of that padding algorithm.
+ * <p>
+ * For compatibility reasons, this method is not declared <i>abstract</i>.
+ * Furthermore, and unless overridden, the default implementation will throw
+ * an {@link UnsupportedOperationException}. Concrete padding algorithms MUST
+ * override this method if they wish to offer an initialisation method that
+ * allows for other than the padding block size parameter to be specified.
+ *
+ * @param attributes a set of name-value pairs that describes the desired
+ * future behaviour of this instance.
+ * @exception IllegalStateException if the instance is already initialised.
+ * @exception IllegalArgumentException if the block size value is invalid.
+ */
+ public void init(Map attributes) throws IllegalStateException
+ {
+ throw new UnsupportedOperationException();
+ }
+
public void reset()
{
blockSize = -1;
diff --git a/gnu/javax/crypto/pad/IPad.java b/gnu/javax/crypto/pad/IPad.java
index 4171220fa..0e3db7db1 100644
--- a/gnu/javax/crypto/pad/IPad.java
+++ b/gnu/javax/crypto/pad/IPad.java
@@ -38,8 +38,10 @@ exception statement from your version. */
package gnu.javax.crypto.pad;
+import java.util.Map;
+
/**
- * The basic visible methods of any padding algorithm.
+ * The basic visible methods, and attribute names, of every padding algorithm.
* <p>
* Padding algorithms serve to <i>pad</i> and <i>unpad</i> byte arrays usually
* as the last step in an <i>encryption</i> or respectively a <i>decryption</i>
@@ -49,6 +51,13 @@ package gnu.javax.crypto.pad;
*/
public interface IPad
{
+ /**
+ * Property name of the block size in which to operate the padding algorithm.
+ * The value associated with this property name is taken to be a positive
+ * {@link Integer} greater than zero.
+ */
+ String PADDING_BLOCK_SIZE = "gnu.crypto.pad.block.size";
+
/** @return the canonical name of this instance. */
String name();
@@ -62,6 +71,19 @@ public interface IPad
void init(int bs) throws IllegalStateException;
/**
+ * Initialises the algorithm with designated attributes. Names, valid and/or
+ * recognisable by all concrete implementations are described in the class
+ * documentation above. Other algorithm-specific attributes MUST be documented
+ * in the implementation class of that padding algorithm.
+ *
+ * @param attributes a set of name-value pairs that describes the desired
+ * future behaviour of this instance.
+ * @exception IllegalStateException if the instance is already initialised.
+ * @exception IllegalArgumentException if the block size value is invalid.
+ */
+ void init(Map attributes) throws IllegalStateException;
+
+ /**
* Returns the byte sequence that should be appended to the designated input.
*
* @param in the input buffer containing the bytes to pad.
diff --git a/gnu/javax/crypto/sasl/plain/PasswordFile.java b/gnu/javax/crypto/sasl/plain/PasswordFile.java
index 8ad225ab9..b6fb3f87e 100644
--- a/gnu/javax/crypto/sasl/plain/PasswordFile.java
+++ b/gnu/javax/crypto/sasl/plain/PasswordFile.java
@@ -38,7 +38,7 @@ exception statement from your version. */
package gnu.javax.crypto.sasl.plain;
-import gnu.classpath.SystemProperties;
+import gnu.java.security.action.GetPropertyAction;
import gnu.javax.crypto.sasl.NoSuchUserException;
import gnu.javax.crypto.sasl.UserAlreadyExistsException;
@@ -50,6 +50,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
+import java.security.AccessController;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.NoSuchElementException;
@@ -63,8 +64,9 @@ public class PasswordFile
private static String DEFAULT_FILE;
static
{
- DEFAULT_FILE = SystemProperties.getProperty(PlainRegistry.PASSWORD_FILE,
- PlainRegistry.DEFAULT_PASSWORD_FILE);
+ DEFAULT_FILE = (String) AccessController.doPrivileged
+ (new GetPropertyAction(PlainRegistry.PASSWORD_FILE,
+ PlainRegistry.DEFAULT_PASSWORD_FILE));
}
private Hashtable entries;
private File passwdFile;
diff --git a/gnu/javax/imageio/gif/GIFStream.java b/gnu/javax/imageio/IIOInputStream.java
index 630d587b8..2638e2fe2 100644
--- a/gnu/javax/imageio/gif/GIFStream.java
+++ b/gnu/javax/imageio/IIOInputStream.java
@@ -35,7 +35,7 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-package gnu.javax.imageio.gif;
+package gnu.javax.imageio;
import java.io.InputStream;
import java.io.IOException;
@@ -43,14 +43,14 @@ import javax.imageio.stream.ImageInputStream;
/**
* Implements InputStream on an ImageInputStream
- * The purpose of this is to avoid IIO dependencies in GIFFile
- * (which only uses read() anyway).
+ * The purpose of this is to avoid IIO dependencies in the various decoders.
+ * (which only use read() anyway).
*/
-public class GIFStream extends InputStream
+public class IIOInputStream extends InputStream
{
private ImageInputStream is;
- public GIFStream( ImageInputStream is )
+ public IIOInputStream( ImageInputStream is )
{
this.is = is;
}
diff --git a/gnu/javax/imageio/gif/GIFImageReader.java b/gnu/javax/imageio/gif/GIFImageReader.java
index 24e3d46db..47108dd0c 100644
--- a/gnu/javax/imageio/gif/GIFImageReader.java
+++ b/gnu/javax/imageio/gif/GIFImageReader.java
@@ -37,6 +37,8 @@ exception statement from your version. */
package gnu.javax.imageio.gif;
+import gnu.javax.imageio.IIOInputStream;
+
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.*;
@@ -74,7 +76,7 @@ public class GIFImageReader extends ImageReader
if( input instanceof InputStream )
file = new GIFFile( (InputStream)input );
else
- file = new GIFFile( new GIFStream((ImageInputStream)input) );
+ file = new GIFFile( new IIOInputStream((ImageInputStream)input) );
}
catch(GIFFile.GIFException ge)
{
@@ -231,9 +233,6 @@ public class GIFImageReader extends ImageReader
new int[] {0xFF});
break;
}
- byte[] bits = f.getRawImage();
- for(int i = 0; i < 5; i++)
- System.out.println("Bits "+i+":"+bits[i]);
DataBuffer db = new DataBufferByte(f.getRawImage(), width * height, 0);
WritableRaster raster = Raster.createWritableRaster(sm, db, null);
diff --git a/gnu/javax/imageio/gif/GIFImageReaderSpi.java b/gnu/javax/imageio/gif/GIFImageReaderSpi.java
index a7b3ceb03..a31848623 100644
--- a/gnu/javax/imageio/gif/GIFImageReaderSpi.java
+++ b/gnu/javax/imageio/gif/GIFImageReaderSpi.java
@@ -37,6 +37,8 @@ exception statement from your version. */
package gnu.javax.imageio.gif;
+import gnu.javax.imageio.IIOInputStream;
+
import java.io.InputStream;
import java.io.IOException;
import java.util.Locale;
@@ -104,7 +106,7 @@ public class GIFImageReaderSpi extends ImageReaderSpi
boolean retval;
InputStream in;
if( input instanceof ImageInputStream )
- in = new GIFStream( (ImageInputStream)input );
+ in = new IIOInputStream( (ImageInputStream)input );
else
in = (InputStream)input;
diff --git a/gnu/javax/imageio/png/PNGChunk.java b/gnu/javax/imageio/png/PNGChunk.java
new file mode 100644
index 000000000..6b53810c8
--- /dev/null
+++ b/gnu/javax/imageio/png/PNGChunk.java
@@ -0,0 +1,284 @@
+/* PNGChunk.java -- Generic PNG chunk
+ 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 gnu.javax.imageio.png;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Class to load and validate a generic PNG chunk.
+ */
+public class PNGChunk
+{
+
+ /**
+ * CRC table and initialization code.
+ */
+ private static long[] crcTable;
+
+ static
+ {
+ long c;
+ crcTable = new long[256];
+
+ for(int i = 0; i < 256; i++)
+ {
+ c = i;
+ for(int j = 0; j < 8; j++)
+ if( (c & 1) == 1 )
+ c = 0xEDB88320L ^ (c >> 1);
+ else
+ c = c >> 1;
+ crcTable[i] = c;
+ }
+ }
+
+ /**
+ * (recognized) PNG chunk types.
+ */
+ public static final int TYPE_HEADER = 0x49484452; // 'IHDR'
+ public static final int TYPE_PALETTE = 0x504c5445;// 'PLTE'
+ public static final int TYPE_DATA = 0x49444154; // 'IDAT'
+ public static final int TYPE_TIME = 0x74494d45; // 'tIME'
+ public static final int TYPE_END = 0x49454e44; // 'IEND'
+ public static final int TYPE_PHYS = 0x70485973; // 'pHYS'
+ public static final int TYPE_GAMMA = 0x67414d41; // 'gAMA'
+ public static final int TYPE_PROFILE = 0x69434350; // 'iCCP'
+
+ /**
+ * The chunk type - Represented in the file as 4 ASCII bytes,
+ */
+ private int type;
+
+ /**
+ * The chunk data
+ */
+ protected byte[] data;
+
+ /**
+ * The chunk's crc
+ */
+ private int crc;
+
+ /**
+ * Constructor for reading a generic chunk.
+ */
+ protected PNGChunk( int type, byte[] data, int crc )
+ {
+ this.type = type;
+ this.data = data;
+ this.crc = crc;
+ }
+
+ /**
+ * Constructor for creating new chunks.
+ * (only used by subclasses - creating a generic chunk is rather useless)
+ */
+ protected PNGChunk( int type )
+ {
+ this.type = type;
+ }
+
+ /**
+ * Loads a chunk from an InputStream. Does not perform validation,
+ * but will throw an IOException if the read fails.
+ * @param in - th einputstream to read from
+ * @param strict - if true, a PNGException is thrown on all invalid chunks,
+ * if false, only critical chunks will throw PNGExceptions.
+ */
+ public static PNGChunk readChunk(InputStream in, boolean strict)
+ throws IOException, PNGException
+ {
+ byte data[] = new byte[4];
+ if( in.read( data ) != 4 )
+ throw new IOException("Could not read chunk length.");
+ int length = ((data[0] & 0xFF) << 24) | ((data[1] & 0xFF) << 16 ) |
+ ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
+
+ if( in.read( data ) != 4 )
+ throw new IOException("Could not read chunk type.");
+ int type = ((data[0] & 0xFF) << 24) | ((data[1] & 0xFF) << 16 ) |
+ ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
+
+ byte[] chkdata = new byte[ length ];
+ if( in.read( chkdata ) != length )
+ throw new IOException("Could not read chunk data.");
+
+ if( in.read( data ) != 4 )
+ throw new IOException("Could not read chunk CRC.");
+
+ int crc = ((data[0] & 0xFF) << 24) | ( (data[1] & 0xFF) << 16 ) |
+ ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
+
+ if( strict )
+ return getChunk( type, chkdata, crc );
+ else
+ {
+ try
+ {
+ return getChunk( type, chkdata, crc );
+ }
+ catch(PNGException pnge)
+ {
+ if( isEssentialChunk( type ) )
+ throw pnge;
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Returns a specialied object for a chunk, if we have one.
+ */
+ private static PNGChunk getChunk( int type, byte[] data, int crc )
+ throws PNGException
+ {
+ switch( type )
+ {
+ case TYPE_HEADER:
+ return new PNGHeader( type, data, crc );
+ case TYPE_DATA:
+ return new PNGData( type, data, crc );
+ case TYPE_PALETTE:
+ return new PNGPalette( type, data, crc );
+ case TYPE_TIME:
+ return new PNGTime( type, data, crc );
+ case TYPE_PHYS:
+ return new PNGPhys( type, data, crc );
+ case TYPE_GAMMA:
+ return new PNGGamma( type, data, crc );
+ case TYPE_PROFILE:
+ return new PNGICCProfile( type, data, crc );
+ default:
+ return new PNGChunk( type, data, crc );
+ }
+ }
+
+ /**
+ * Returns whether the chunk is essential or not
+ */
+ private static boolean isEssentialChunk( int type )
+ {
+ switch( type )
+ {
+ case TYPE_HEADER:
+ case TYPE_DATA:
+ case TYPE_PALETTE:
+ case TYPE_END:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Validates the chunk
+ */
+ public boolean isValidChunk()
+ {
+ return (crc == calcCRC());
+ }
+
+ /**
+ * Returns the chunk type.
+ */
+ public int getType()
+ {
+ return type;
+ }
+
+ /**
+ * Writes a PNG chunk to an output stream,
+ * performing the CRC calculation as well.
+ */
+ public void writeChunk(OutputStream out) throws IOException
+ {
+ out.write( getInt(data.length) );
+ out.write( getInt(type) );
+ out.write( data );
+ out.write( getInt(calcCRC()) );
+ }
+
+ /**
+ * Return whether the chunk contains any data.
+ */
+ public boolean isEmpty()
+ {
+ return ( data.length == 0 );
+ }
+
+ /**
+ * Convenience method. Cast an int to four bytes (big endian).
+ * (Now why doesn't java have a simple way of doing this?)
+ */
+ public static byte[] getInt(int intValue)
+ {
+ long i = (intValue & 0xFFFFFFFFL);
+ byte[] b = new byte[4];
+ b[0] = (byte)((i & 0xFF000000L) >> 24);
+ b[1] = (byte)((i & 0x00FF0000L) >> 16);
+ b[2] = (byte)((i & 0x0000FF00L) >> 8);
+ b[3] = (byte)(i & 0x000000FFL);
+ return b;
+ }
+
+ /**
+ * Calculates this chunk's CRC value.
+ */
+ private int calcCRC()
+ {
+ long c = 0xFFFFFFFFL;
+ byte[] t = getInt( type );
+ for(int i = 0; i < 4; i++)
+ c = crcTable[ (int)((c ^ t[i]) & 0xFF) ] ^ (c >> 8);
+
+ for(int i = 0; i < data.length; i++)
+ c = crcTable[ (int)((c ^ data[i]) & 0xFF) ] ^ (c >> 8);
+
+ return (int)(c ^ 0xFFFFFFFFL);
+ }
+
+ public String toString()
+ {
+ return "PNG Chunk. Type: " + new String( getInt(type) ) + " , CRC: " +
+ crc + " , calculated CRC: "+calcCRC();
+ }
+
+}
diff --git a/gnu/javax/imageio/png/PNGData.java b/gnu/javax/imageio/png/PNGData.java
new file mode 100644
index 000000000..2a8f8aa2d
--- /dev/null
+++ b/gnu/javax/imageio/png/PNGData.java
@@ -0,0 +1,104 @@
+/* PNGData.java -- PNG IDAT chunk.
+ 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 gnu.javax.imageio.png;
+
+import java.util.zip.Inflater;
+import java.util.zip.Deflater;
+
+/**
+ * A PNG IDAT (data) chunk.
+ */
+public class PNGData extends PNGChunk
+{
+ private int offset;
+
+ protected PNGData( int type, byte[] data, int crc )
+ {
+ super( type, data, crc );
+ }
+
+ protected PNGData( int chunkSize )
+ {
+ super( PNGChunk.TYPE_DATA );
+ data = new byte[ chunkSize ];
+ offset = 0;
+ }
+
+ /**
+ * Deflates the available data in def to the chunk.
+ *
+ * @return true if the chunk is filled and no more data can be written,
+ * false otherwise.
+ */
+ public void deflateToChunk( Deflater def )
+ {
+ offset += def.deflate( data, offset, data.length - offset );
+ }
+
+ /**
+ * Returns true if the chunk is filled.
+ */
+ public boolean chunkFull()
+ {
+ return (offset >= data.length);
+ }
+
+ /**
+ * Shrink the chunk to offset size, used for the last chunk in a stream
+ * (no trailing data!)
+ */
+ public void shrink()
+ {
+ byte[] newData = new byte[ offset ];
+ System.arraycopy( data, 0, newData, 0, offset );
+ data = newData;
+ }
+
+ /**
+ * Feeds the data in the chunk to a ZIP inflater object.
+ */
+ public void feedToInflater( Inflater inf )
+ {
+ inf.setInput( data );
+ }
+
+ public String toString()
+ {
+ return "PNG Data chunk. Length = "+data.length;
+ }
+}
diff --git a/gnu/javax/imageio/png/PNGDecoder.java b/gnu/javax/imageio/png/PNGDecoder.java
new file mode 100644
index 000000000..20fc32ce3
--- /dev/null
+++ b/gnu/javax/imageio/png/PNGDecoder.java
@@ -0,0 +1,331 @@
+/* PNGDecoder.java
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.png;
+
+import java.util.zip.Inflater;
+import java.util.zip.DataFormatException;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.ComponentSampleModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferUShort;
+import java.awt.image.IndexColorModel;
+import java.awt.image.MultiPixelPackedSampleModel;
+import java.awt.image.Raster;
+import java.awt.image.SampleModel;
+import java.awt.image.SinglePixelPackedSampleModel;
+import java.awt.image.WritableRaster;
+import java.awt.color.ColorSpace;
+
+public class PNGDecoder
+{
+ private PNGHeader header;
+ private byte[] raster;
+ private byte[] scanline, lastScanline;
+ private byte[] filterType;
+ private int offset, length;
+ private int currentScanline;
+ private final int stride;
+ private Inflater inflater;
+ private boolean readFilter;
+ private int bpp; // bytes per pixel
+
+ /**
+ * Constructs a filter object for
+ */
+ public PNGDecoder(PNGHeader header)
+ {
+ this.header = header;
+ offset = 0;
+ inflater = new Inflater();
+ stride = header.getScanlineStride();
+ length = stride * header.getHeight();
+
+ // Allocate the output raster
+ raster = new byte[ length ];
+ scanline = new byte[ stride ];
+ lastScanline = new byte[ stride ];
+ currentScanline = 0;
+ readFilter = true;
+ bpp = header.bytesPerPixel();
+ filterType = new byte[1];
+ inflater = new Inflater();
+ }
+
+ private int getBytes( byte[] buf, int offset ) throws PNGException
+ {
+ try
+ {
+ return inflater.inflate( buf, offset, buf.length - offset);
+ }
+ catch(DataFormatException dfe)
+ {
+ throw new PNGException("Error inflating data.");
+ }
+ }
+
+ /**
+ * Decodes a data chunk.
+ */
+ public void addData( PNGData chunk ) throws PNGException
+ {
+ int n = 0;
+ if( isFinished() )
+ return;
+ chunk.feedToInflater( inflater );
+ do
+ {
+ if( readFilter )
+ if( getBytes( filterType, 0 ) < 1 )
+ return;
+
+ n = getBytes( scanline, offset );
+
+ if( offset + n < stride )
+ {
+ offset += n;
+ readFilter = false;
+ }
+ else
+ {
+ scanline = PNGFilter.unFilterScanline( filterType[0], scanline,
+ lastScanline, bpp );
+ System.arraycopy( scanline, 0,
+ raster, currentScanline * stride, stride );
+ lastScanline = scanline;
+ scanline = new byte[scanline.length];
+ currentScanline++;
+ readFilter = true;
+ offset = 0;
+ }
+ }
+ while( n > 0 && currentScanline < header.getHeight() );
+ }
+
+ /**
+ * Parse the appropriate color type and create an AWT raster for it.
+ * @param raster - the file header.
+ */
+ public WritableRaster getRaster( PNGHeader header )
+ {
+ SampleModel sm = null;
+ DataBuffer db = null;
+ int t;
+ int width = header.getWidth();
+ int height = header.getHeight();
+ int depth = header.getDepth();
+
+ switch( header.getColorType() )
+ {
+ case PNGHeader.GRAYSCALE_WITH_ALPHA:
+ if( depth == 8 )
+ {
+ t = DataBuffer.TYPE_BYTE;
+ db = getByteBuffer();
+ }
+ else
+ {
+ t = DataBuffer.TYPE_USHORT;
+ db = getShortBuffer();
+ }
+ sm = new ComponentSampleModel(t, width, height, 2, width * 2,
+ new int[]{0, 1});
+ break;
+
+ case PNGHeader.GRAYSCALE:
+ switch( depth )
+ {
+ case 16:
+ sm = new ComponentSampleModel(DataBuffer.TYPE_USHORT,
+ width, height, 1, width,
+ new int[]{ 0 });
+ db = getShortBuffer();
+ break;
+
+ case 8:
+ sm = new ComponentSampleModel(DataBuffer.TYPE_BYTE,
+ width, height, 1, width,
+ new int[]{ 0 });
+ db = getByteBuffer();
+ break;
+
+ default:
+ sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE,
+ width, height, depth);
+ db = getByteBuffer();
+ break;
+ }
+ break;
+
+ case PNGHeader.RGB:
+ if( depth == 8 )
+ {
+ t = DataBuffer.TYPE_BYTE;
+ db = getByteBuffer();
+ }
+ else
+ {
+ t = DataBuffer.TYPE_USHORT;
+ db = getShortBuffer();
+ }
+ sm = new ComponentSampleModel(t, width, height, 3, 3 * width,
+ new int[]{0, 1, 2});
+ break;
+
+ case PNGHeader.RGB_WITH_ALPHA:
+ if( depth == 8 )
+ {
+ t = DataBuffer.TYPE_BYTE;
+ db = getByteBuffer();
+ }
+ else
+ {
+ t = DataBuffer.TYPE_USHORT;
+ db = getShortBuffer();
+ }
+
+ sm = new ComponentSampleModel(t, width, height, 4, width * 4,
+ new int[]{0, 1, 2, 3});
+ break;
+
+ case PNGHeader.INDEXED:
+ if( depth == 8 )
+ sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_BYTE,
+ width, height,
+ new int[] {0xFF});
+ else
+ sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE,
+ width, height, depth);
+ db = getByteBuffer();
+ break;
+ }
+
+ return Raster.createWritableRaster(sm, db, null);
+ }
+
+ /**
+ * Wrap the raster with a DataBufferUShort,
+ * conversion is big-endian (PNG native).
+ */
+ private DataBuffer getShortBuffer()
+ {
+ short[] data = new short[(raster.length >> 1)];
+ for( int i = 0; i < data.length; i++ )
+ data[i] = (short)(((raster[i * 2] & 0xFF) << 8) |
+ (raster[i * 2 + 1] & 0xFF));
+ return new DataBufferUShort( data, data.length );
+ }
+
+ /**
+ * Wrap the raster with a DataBufferByte
+ */
+ private DataBuffer getByteBuffer()
+ {
+ return new DataBufferByte( raster, raster.length );
+ }
+
+ public ColorModel getColorModel( ColorSpace cs,
+ int colorType, int depth )
+ {
+ int[] bits;
+ boolean hasAlpha = false;
+ int transferType;
+
+ switch( colorType )
+ {
+ case PNGHeader.GRAYSCALE_WITH_ALPHA:
+ if( cs == null )
+ cs = ColorSpace.getInstance( ColorSpace.CS_GRAY );
+ hasAlpha = true;
+ bits = new int[]{ depth, depth };
+ break;
+
+ case PNGHeader.RGB:
+ bits = new int[]{ depth, depth, depth };
+ break;
+
+ case PNGHeader.RGB_WITH_ALPHA:
+ hasAlpha = true;
+ bits = new int[]{ depth, depth, depth, depth };
+ break;
+
+ case PNGHeader.GRAYSCALE:
+ if( depth < 8 )
+ return grayPalette( depth );
+
+ if( cs == null )
+ cs = ColorSpace.getInstance( ColorSpace.CS_GRAY );
+ bits = new int[]{ depth };
+ break;
+
+ default:
+ case PNGHeader.INDEXED:
+ return null; // Handled by the palette chunk.
+ }
+
+ if( cs == null )
+ cs = ColorSpace.getInstance( ColorSpace.CS_sRGB );
+
+
+ return new ComponentColorModel(cs, bits, hasAlpha, false,
+ (hasAlpha ?
+ ComponentColorModel.TRANSLUCENT :
+ ComponentColorModel.OPAQUE),
+ ((depth == 16) ? DataBuffer.TYPE_USHORT :
+ DataBuffer.TYPE_BYTE));
+ }
+
+ private IndexColorModel grayPalette(int depth)
+ {
+ byte[] c = new byte[ (1 << depth) ];
+ for(int i = 0; i < c.length; i++)
+ c[i] = (byte)(255.0 * (((double)i) / ((double)c.length - 1.0)));
+ return new IndexColorModel(8, c.length, c, c, c);
+ }
+
+ public byte[] getRaster()
+ {
+ return raster;
+ }
+
+ public boolean isFinished()
+ {
+ return currentScanline >= header.getHeight();
+ }
+}
diff --git a/gnu/javax/imageio/png/PNGEncoder.java b/gnu/javax/imageio/png/PNGEncoder.java
new file mode 100644
index 000000000..c0a30a7ba
--- /dev/null
+++ b/gnu/javax/imageio/png/PNGEncoder.java
@@ -0,0 +1,235 @@
+/* PNGEncoder.java --
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.png;
+
+import java.util.Vector;
+import java.util.zip.Deflater;
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_Profile;
+import java.awt.color.ICC_ColorSpace;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferUShort;
+import java.awt.image.IndexColorModel;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+
+public class PNGEncoder
+{
+ /**
+ * The default data chunk size. 8 kb.
+ */
+ private static final int defaultChunkSize = 8192;
+
+ private PNGHeader header;
+ private PNGPalette palette;
+ private int stride, bpp;
+ private byte[] rawData;
+ private PNGICCProfile profile;
+
+ public PNGEncoder( BufferedImage bi ) throws PNGException
+ {
+ ColorModel c = bi.getColorModel();
+ int width = bi.getWidth();
+ int height = bi.getHeight();
+ int depth = 0;
+ int colorType;
+ boolean interlace = false;
+
+ if( c instanceof IndexColorModel )
+ {
+ colorType = PNGHeader.INDEXED;
+ int n = ((IndexColorModel)c).getMapSize();
+ if( n <= 2 )
+ depth = 1;
+ else if( n <= 4 )
+ depth = 2;
+ else if( n <= 16 )
+ depth = 4;
+ else if( n <= 256 )
+ depth = 8;
+ else
+ throw new PNGException("Depth must be <= 8 bits for indexed color.");
+ palette = new PNGPalette( ((IndexColorModel)c) );
+ }
+ else
+ {
+ ColorSpace cs = c.getColorSpace();
+ ColorSpace grayCS = ColorSpace.getInstance( ColorSpace.CS_GRAY );
+ if( cs == grayCS || bi.getType() == BufferedImage.TYPE_BYTE_GRAY
+ || bi.getType() == BufferedImage.TYPE_USHORT_GRAY )
+ colorType = c.hasAlpha() ? PNGHeader.GRAYSCALE_WITH_ALPHA :
+ PNGHeader.GRAYSCALE;
+ else
+ colorType = c.hasAlpha() ? PNGHeader.RGB_WITH_ALPHA : PNGHeader.RGB;
+ // Figure out the depth
+ int[] bits = c.getComponentSize();
+ depth = bits[0];
+ for(int i = 1; i < bits.length; i++ )
+ if( bits[i] > depth ) depth = bits[i];
+ if( (cs != grayCS && !cs.isCS_sRGB()) && cs instanceof ICC_ColorSpace )
+ profile = new PNGICCProfile( ((ICC_ColorSpace)cs).getProfile() );
+ }
+
+ header = new PNGHeader(width, height, depth, colorType, interlace);
+
+ stride = header.getScanlineStride(); // scanline stride
+ bpp = header.bytesPerPixel(); // bytes per pixel
+ getRawData( bi );
+ }
+
+ /**
+ * Returns the generated header.
+ */
+ public PNGHeader getHeader()
+ {
+ return header;
+ }
+
+ /**
+ * Returns the generated palette.
+ */
+ public PNGPalette getPalette()
+ {
+ return palette;
+ }
+
+ /**
+ * Returns the associated ICC profile, if any.
+ */
+ public PNGICCProfile getProfile()
+ {
+ return profile;
+ }
+
+ /**
+ * Encodes the raster and returns a Vector of PNGData chunks.
+ */
+ public Vector encodeImage()
+ {
+ Deflater deflater = new Deflater(); // The deflater
+ boolean useFilter = PNGFilter.useFilter( header );
+ byte[] lastScanline = new byte[ stride ];
+
+ byte[] data = new byte[ rawData.length + header.getHeight() ];
+
+ byte filterByte = PNGFilter.FILTER_NONE;
+ for( int i = 0; i < header.getHeight(); i++)
+ {
+ byte[] scanline = new byte[ stride ];
+ System.arraycopy(rawData, (i * stride), scanline, 0, stride);
+ if( useFilter && i > 0)
+ filterByte = PNGFilter.chooseFilter( scanline, lastScanline, bpp);
+
+ byte[] filtered = PNGFilter.filterScanline( filterByte, scanline,
+ lastScanline, bpp );
+ data[i * (stride + 1)] = filterByte;
+ System.arraycopy(filtered, 0, data, 1 + (i * (stride + 1)), stride);
+
+ lastScanline = scanline;
+ }
+
+ deflater.setInput( data );
+ deflater.finish();
+
+ PNGData chunk;
+ Vector chunks = new Vector();
+ do
+ {
+ chunk = new PNGData( defaultChunkSize );
+ chunk.deflateToChunk( deflater );
+ chunks.add( chunk );
+ }
+ while( chunk.chunkFull() );
+ chunk.shrink(); // Shrink the last chunk.
+ return chunks;
+ }
+
+ /**
+ * Get the image's raw data.
+ * FIXME: This may need improving on.
+ */
+ private void getRawData( BufferedImage bi ) throws PNGException
+ {
+ WritableRaster raster = bi.getRaster();
+ rawData = new byte[ stride * header.getHeight() ];
+ if( header.isIndexed() )
+ {
+ DataBuffer db = raster.getDataBuffer();
+ if( !( db instanceof DataBufferByte ) )
+ throw new PNGException("Unexpected DataBuffer for an IndexColorModel.");
+ byte[] data = ((DataBufferByte)db).getData();
+ for(int i = 0; i < header.getHeight(); i++ )
+ System.arraycopy( data, i * stride, rawData, i * stride, stride );
+ return;
+ }
+
+ if( header.getDepth() == 16 )
+ {
+ DataBuffer db = raster.getDataBuffer();
+ if( !( db instanceof DataBufferUShort ) )
+ throw new PNGException("Unexpected DataBuffer for 16-bit.");
+ short[] data = ((DataBufferUShort)db).getData();
+ for(int i = 0; i < header.getHeight(); i++ )
+ for(int j = 0; j < ( stride >> 1); j++)
+ {
+ rawData[ j * 2 + i * stride ] = (byte)((data[j + i * (stride >> 1 )] & 0xFF00) >> 8);
+ rawData[ j * 2 + i * stride + 1 ] = (byte)(data[j + i * (stride >> 1 )] & 0xFF);
+ }
+ return;
+ }
+
+ int size = ( header.getColorType() == PNGHeader.RGB_WITH_ALPHA ) ? 4 : 3;
+ int width = header.getWidth();
+ int height = header.getHeight();
+ int[] pixels = bi.getRGB( 0, 0, width, height, null, 0, width );
+
+ for( int i = 0; i < width * height; i++ )
+ {
+ rawData[ i * size ] = (byte)((pixels[i] & 0xFF0000) >> 16);
+ rawData[ i * size + 1 ] = (byte)((pixels[i] & 0xFF00) >> 8);
+ rawData[ i * size + 2 ] = (byte)(pixels[i] & 0xFF);
+ }
+
+ if( size == 4 )
+ for( int i = 0; i < width * height; i++ )
+ rawData[ i * size + 3 ] = (byte)((pixels[i] & 0xFF000000) >> 24);
+ }
+}
diff --git a/gnu/javax/imageio/png/PNGException.java b/gnu/javax/imageio/png/PNGException.java
new file mode 100644
index 000000000..67486e579
--- /dev/null
+++ b/gnu/javax/imageio/png/PNGException.java
@@ -0,0 +1,48 @@
+/* PNGException.java --
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.png;
+
+import java.io.IOException;
+
+public class PNGException extends IOException
+{
+ public PNGException(String msg)
+ {
+ super( msg );
+ }
+}
diff --git a/gnu/javax/imageio/png/PNGFile.java b/gnu/javax/imageio/png/PNGFile.java
new file mode 100644
index 000000000..cc0ca297f
--- /dev/null
+++ b/gnu/javax/imageio/png/PNGFile.java
@@ -0,0 +1,258 @@
+/* PNGFile.java -- High-level representation of a PNG file.
+ 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 gnu.javax.imageio.png;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.util.Vector;
+import java.awt.image.BufferedImage;
+import java.awt.image.WritableRaster;
+import java.awt.image.ColorModel;
+import java.awt.image.IndexColorModel;
+import java.awt.color.ColorSpace;
+
+public class PNGFile
+{
+ /**
+ * The PNG file signature.
+ */
+ private static final byte[] signature = new byte[]
+ { (byte)137, 80, 78, 71, 13, 10, 26, 10 };
+
+ /**
+ * The end chunk in raw form, no need for anything fancy here, it's just
+ * 0 bytes of length, the "IEND" tag and its CRC.
+ */
+ private static final byte[] endChunk = new byte[]
+ { 0, 0, 0, 0, (byte)0x49, (byte)0x45, (byte)0x4E, (byte)0x44,
+ (byte)0xAE, (byte)0x42, (byte)0x60, (byte)0x82 };
+
+ /**
+ * The loaded data.
+ */
+ private Vector chunks;
+
+ /**
+ * The Header chunk
+ */
+ private PNGHeader header;
+
+ /**
+ * Whether this file has a palette chunk or not.
+ */
+ private boolean hasPalette;
+
+ /**
+ * Image width and height.
+ */
+ private int width, height;
+
+ /**
+ * The decoder, if any.
+ */
+ private PNGDecoder decoder;
+
+ /**
+ * The encoder, if any. (Either this or the above must exist).
+ */
+ private PNGEncoder encoder;
+
+ /**
+ * The source of this PNG (if encoding)
+ */
+ private BufferedImage sourceImage;
+
+ /**
+ * Creates a PNGFile object from an InputStream.
+ */
+ public PNGFile(InputStream in) throws IOException, PNGException
+ {
+ PNGChunk chunk;
+ byte[] fileHdr = new byte[8];
+ chunks = new Vector();
+ hasPalette = false;
+
+ if( in.read( fileHdr ) != 8 )
+ throw new IOException("Could not read file header.");
+ if( !validateHeader( fileHdr ) )
+ throw new PNGException("Invalid file header. Not a PNG file.");
+
+ chunk = PNGChunk.readChunk( in, false );
+ if( !(chunk instanceof PNGHeader) )
+ throw new PNGException("First chunk not a header chunk.");
+ header = (PNGHeader)chunk;
+ if( !header.isValidChunk() )
+ throw new PNGException("First chunk not a valid header.");
+ System.out.println(header);
+
+ decoder = new PNGDecoder( header );
+ // Read chunks.
+ do
+ {
+ chunk = PNGChunk.readChunk( in, false );
+ /*
+ * We could exit here or output some kind of warning.
+ * But in the meantime, we'll just silently drop invalid chunks.
+ */
+ if( chunk.isValidChunk() )
+ {
+ if( chunk instanceof PNGData )
+ decoder.addData( (PNGData)chunk );
+ else // Silently ignore multiple headers, and use only the first.
+ if( chunk.getType() != PNGChunk.TYPE_END )
+ {
+ chunks.add( chunk );
+ hasPalette |= ( chunk instanceof PNGPalette );
+ }
+ }
+ else
+ System.out.println("WARNING: Invalid chunk!");
+ }
+ while( chunk.getType() != PNGChunk.TYPE_END );
+
+ if( header.isIndexed() && !hasPalette )
+ throw new PNGException("File is indexed color and has no palette.");
+
+ width = header.getWidth();
+ height = header.getHeight();
+ }
+
+ /**
+ * Creates a PNG file from an existing BufferedImage.
+ */
+ public PNGFile(BufferedImage bi) throws PNGException
+ {
+ sourceImage = bi;
+ width = bi.getWidth();
+ height = bi.getHeight();
+ chunks = new Vector();
+ encoder = new PNGEncoder( bi );
+ header = encoder.getHeader();
+ if( header.isIndexed() )
+ chunks.add( encoder.getPalette() );
+
+ // Do the compression and put the data chunks in the list.
+ chunks.addAll( encoder.encodeImage() );
+ }
+
+ /**
+ * Writes a PNG file to an OutputStream
+ */
+ public void writePNG(OutputStream out) throws IOException
+ {
+ out.write( signature ); // write the signature.
+ header.writeChunk( out );
+ for( int i = 0; i < chunks.size(); i++ )
+ {
+ PNGChunk chunk = ((PNGChunk)chunks.elementAt(i));
+ chunk.writeChunk( out );
+ }
+ out.write( endChunk );
+ }
+
+ /**
+ * Check 8 bytes to see if it's a valid PNG header.
+ */
+ private boolean validateHeader( byte[] hdr )
+ {
+ if( hdr.length != 8 )
+ return false;
+ for( int i = 0; i < 8; i++ )
+ if( signature[i] != hdr[i] )
+ return false;
+ return true;
+ }
+
+ /**
+ * Return a loaded image as a bufferedimage.
+ */
+ public BufferedImage getBufferedImage()
+ {
+ if( decoder == null )
+ return sourceImage;
+
+ WritableRaster r = decoder.getRaster( header );
+ ColorModel cm;
+ if( header.isIndexed() )
+ {
+ PNGPalette pngp = getPalette();
+ cm = pngp.getPalette( getColorSpace() );
+ }
+ else
+ cm = decoder.getColorModel( getColorSpace(),
+ header.getColorType(),
+ header.getDepth() );
+
+ return new BufferedImage(cm, r, false, null);
+ }
+
+ /**
+ * Find the palette chunk and return it
+ */
+ private PNGPalette getPalette()
+ {
+ for(int i = 0; i < chunks.size(); i++ )
+ if( chunks.elementAt(i) instanceof PNGPalette )
+ return ((PNGPalette)chunks.elementAt(i));
+ return null;
+ }
+
+ /**
+ * Return the Color space to use, first preference is ICC profile, then
+ * a gamma chunk, or returns null for the default sRGB.
+ */
+ private ColorSpace getColorSpace()
+ {
+ PNGICCProfile icc = null;
+ PNGGamma gamma = null;
+ for(int i = 0; i < chunks.size(); i++ )
+ {
+ if( chunks.elementAt(i) instanceof PNGICCProfile )
+ icc = ((PNGICCProfile)chunks.elementAt(i));
+ else if(chunks.elementAt(i) instanceof PNGGamma )
+ gamma = ((PNGGamma)chunks.elementAt(i));
+ }
+
+ if( icc != null )
+ return icc.getColorSpace();
+// if( gamma != null && !header.isGrayscale())
+// return gamma.getColorSpace( header.isGrayscale() );
+ return null;
+ }
+}
diff --git a/gnu/javax/imageio/png/PNGFilter.java b/gnu/javax/imageio/png/PNGFilter.java
new file mode 100644
index 000000000..63af19929
--- /dev/null
+++ b/gnu/javax/imageio/png/PNGFilter.java
@@ -0,0 +1,237 @@
+/* PNGFilter.java -- PNG image filters.
+ 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 gnu.javax.imageio.png;
+
+/**
+ * A utility class of static methods implementing the PNG filtering algorithms.
+ */
+public class PNGFilter
+{
+
+ public static final byte FILTER_NONE = 0;
+ public static final byte FILTER_SUB = 1;
+ public static final byte FILTER_UP = 2;
+ public static final byte FILTER_AVERAGE = 3;
+ public static final byte FILTER_PAETH = 4;
+
+ /**
+ * Return whether a filter should be used or FILTER_NONE,
+ * following the recommendations in the PNG spec.
+ */
+ public static boolean useFilter( PNGHeader header )
+ {
+ switch( header.getColorType() )
+ {
+ case PNGHeader.INDEXED:
+ return false;
+
+ case PNGHeader.GRAYSCALE:
+ case PNGHeader.RGB:
+ if( header.bytesPerPixel() <= 1 )
+ return false;
+ case PNGHeader.GRAYSCALE_WITH_ALPHA:
+ case PNGHeader.RGB_WITH_ALPHA:
+ default:
+ return true;
+ }
+ }
+
+ /**
+ * Heuristic for adaptively choosing a filter, following the scheme
+ * suggested in the PNG spec.
+ * @return a fiter type.
+ */
+ public static byte chooseFilter( byte[] scanline, byte[] lastScanline,
+ int bpp)
+
+ {
+ long[] values = new long[5];
+ int idx = 0;
+ for( int i = 0; i < 5; i++ )
+ {
+ byte[] filtered = filterScanline((byte)i, scanline, lastScanline, bpp);
+ values[i] = 0;
+ for(int j = 0; j < filtered.length; j++ )
+ values[i] += (int)(filtered[j] & 0xFF);
+ if( values[ idx ] > values[i] )
+ idx = i;
+ }
+ return (byte)idx;
+ }
+
+ /**
+ * Filter a scanline.
+ */
+ public static byte[] filterScanline( byte filtertype, byte[] scanline,
+ byte[] lastScanline, int bpp)
+ {
+ int stride = scanline.length;
+ byte[] out = new byte[ stride ];
+ switch( filtertype )
+ {
+ case FILTER_SUB:
+ for( int i = 0; i < bpp; i++)
+ out[ i ] = scanline[ i ];
+
+ for( int i = bpp; i < stride; i++ )
+ out[i] = (byte)(scanline[ i ] -
+ scanline[ i - bpp ]);
+ break;
+
+ case FILTER_UP:
+ for( int i = 0; i < stride; i++ )
+ out[ i ] = (byte)(scanline[ i ] - lastScanline[ i ]);
+ break;
+
+ case FILTER_AVERAGE:
+ for( int i = 0; i < bpp; i++)
+ out[ i ] = (byte)((scanline[ i ] & 0xFF) - ((lastScanline[ i ] & 0xFF) >> 1));
+ for( int i = bpp; i < stride; i++ )
+ out[ i ] = (byte)((scanline[ i ] & 0xFF) -
+ (((scanline[ i - bpp ] & 0xFF) +
+ (lastScanline[ i ] & 0xFF)) >> 1));
+ break;
+
+ case FILTER_PAETH:
+ for( int i = 0; i < stride; i++ )
+ {
+ int x;
+ {
+ int a, b, c;
+ if( i >= bpp )
+ {
+ a = (scanline[ i - bpp ] & 0xFF); // left
+ c = (lastScanline[ i - bpp ] & 0xFF); // upper-left
+ }
+ else
+ a = c = 0;
+ b = (lastScanline[ i ] & 0xFF); // up
+
+ int p = (a + b - c); // initial estimate
+ // distances to a, b, c
+ int pa = (p > a) ? p - a : a - p;
+ int pb = (p > b) ? p - b : b - p;
+ int pc = (p > c) ? p - c : c - p;
+ // return nearest of a,b,c,
+ // breaking ties in order a,b,c.
+ if( pa <= pb && pa <= pc ) x = a;
+ else { if( pb <= pc ) x = b;
+ else x = c;
+ }
+ }
+ out[ i ] = (byte)(scanline[ i ] - x);
+ }
+ break;
+ default:
+ case FILTER_NONE:
+ return scanline;
+ }
+ return out;
+ }
+
+ /**
+ * Unfilter a scanline.
+ */
+ public static byte[] unFilterScanline( int filtertype, byte[] scanline,
+ byte[] lastScanline, int bpp)
+ {
+ int stride = scanline.length;
+ byte[] out = new byte[ stride ];
+ switch( filtertype )
+ {
+
+ case FILTER_NONE:
+ System.arraycopy( scanline, 0, out, 0, stride );
+ break;
+
+ case FILTER_SUB:
+ for( int i = 0; i < bpp; i++)
+ out[ i ] = scanline[ i ];
+
+ for( int i = bpp; i < stride; i++ )
+ out[ i ] = (byte)(scanline[ i ] +
+ out[ i - bpp ]);
+ break;
+
+ case FILTER_UP:
+ for( int i = 0; i < stride; i++ )
+ out[ i ] = (byte)(scanline[ i ] + lastScanline[ i ]);
+ break;
+
+ case FILTER_AVERAGE:
+ for( int i = 0; i < bpp; i++)
+ out[ i ] = (byte)((scanline[ i ] & 0xFF) + ((lastScanline[ i ] & 0xFF) >> 1));
+ for( int i = bpp; i < stride; i++ )
+ out[ i ] = (byte)((scanline[ i ] & 0xFF) +
+ (((out[ i - bpp ] & 0xFF) + (lastScanline[ i ] & 0xFF)) >> 1));
+ break;
+
+ case FILTER_PAETH:
+ for( int i = 0; i < stride; i++ )
+ {
+ int x;
+ {
+ int a, b, c;
+ if( i >= bpp )
+ {
+ a = (out[ i - bpp ] & 0xFF); // left
+ c = (lastScanline[ i - bpp ] & 0xFF); // upper-left
+ }
+ else
+ a = c = 0;
+ b = (lastScanline[ i ] & 0xFF); // up
+
+ int p = (a + b - c); // initial estimate
+ // distances to a, b, c
+ int pa = (p > a) ? p - a : a - p;
+ int pb = (p > b) ? p - b : b - p;
+ int pc = (p > c) ? p - c : c - p;
+ // return nearest of a,b,c,
+ // breaking ties in order a,b,c.
+ if( pa <= pb && pa <= pc ) x = a;
+ else { if( pb <= pc ) x = b;
+ else x = c;
+ }
+ }
+ out[ i ] = (byte)(scanline[ i ] + x);
+ }
+ break;
+ }
+ return out;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/imageio/png/PNGGamma.java b/gnu/javax/imageio/png/PNGGamma.java
new file mode 100644
index 000000000..af777d9b4
--- /dev/null
+++ b/gnu/javax/imageio/png/PNGGamma.java
@@ -0,0 +1,89 @@
+/* PNGGamma.java -- GAMA chunk.
+ 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 gnu.javax.imageio.png;
+
+import java.awt.color.ICC_ProfileGray;
+import java.awt.color.ICC_ProfileRGB;
+import java.awt.color.ICC_Profile;
+import java.awt.color.ICC_ColorSpace;
+import java.awt.color.ColorSpace;
+
+/**
+ * A PNG gAMA (gamma) chunk.
+ */
+public class PNGGamma extends PNGChunk
+{
+ private double gamma;
+
+ protected PNGGamma( int type, byte[] data, int crc ) throws PNGException
+ {
+ super( type, data, crc );
+ if( data.length < 4 )
+ throw new PNGException("Unexpectedly short time chunk. ("+data.length+" bytes)");
+ long g = ((data[0] & 0xFF) << 24) | ( (data[1] & 0xFF) << 16 ) |
+ ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
+ gamma = (double)g;
+ gamma = 100000.0/gamma;
+ }
+
+ public PNGGamma( double g )
+ {
+ super( TYPE_GAMMA );
+ data = new byte[ 4 ];
+ gamma = g;
+ long tmp = (long)(100000.0/gamma);
+ data[0] = (byte)((tmp & 0xFF000000) >> 24);
+ data[1] = (byte)((tmp & 0xFF0000) >> 16);
+ data[2] = (byte)((tmp & 0xFF00) >> 8);
+ data[3] = (byte)(tmp & 0xFF);
+ }
+
+ /**
+ * Returns a ColorSpace object corresponding to this gamma value.
+ */
+ public ColorSpace getColorSpace(boolean grayscale)
+ {
+ // FIXME.
+ return null;
+ }
+
+ public String toString()
+ {
+ return "PNG Gamma chunk, value: "+gamma;
+ }
+}
diff --git a/gnu/javax/imageio/png/PNGHeader.java b/gnu/javax/imageio/png/PNGHeader.java
new file mode 100644
index 000000000..c9ef2dc37
--- /dev/null
+++ b/gnu/javax/imageio/png/PNGHeader.java
@@ -0,0 +1,257 @@
+/* PNGHeader.java -- PNG Header
+ 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 gnu.javax.imageio.png;
+
+/**
+ * A PNG Header chunk.
+ */
+public class PNGHeader extends PNGChunk
+{
+ private int width, height, depth;
+ private int colorType, compression, filter, interlace;
+
+ /**
+ * The valid interlace types.
+ */
+ public static final int INTERLACE_NONE = 0;
+ public static final int INTERLACE_ADAM7 = 1;
+
+ /**
+ * The valid color types.
+ */
+ public static final int GRAYSCALE = 0;
+ public static final int RGB = 2;
+ public static final int INDEXED = 3;
+ public static final int GRAYSCALE_WITH_ALPHA = 4;
+ public static final int RGB_WITH_ALPHA = 6;
+
+ /**
+ * Parses a PNG Header chunk.
+ */
+ protected PNGHeader( int type, byte[] data, int crc ) throws PNGException
+ {
+ super( type, data, crc );
+ if( data.length < 13 )
+ throw new PNGException("Unexpectedly short header chunk. (" + data.length
+ + " bytes)");
+
+ width = ((data[0] & 0xFF) << 24) | ( (data[1] & 0xFF) << 16 ) |
+ ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
+ height = ((data[4] & 0xFF) << 24) | ( (data[5] & 0xFF) << 16 ) |
+ ((data[6] & 0xFF) << 8) | (data[7] & 0xFF);
+ depth = (data[8] & 0xFF);
+ colorType = (data[9] & 0xFF);
+ compression = (data[10] & 0xFF);
+ filter = (data[11] & 0xFF);
+ interlace = (data[12] & 0xFF);
+ }
+
+ /**
+ * Create a PNG header chunk.
+ * Warning: This trusts that the parameters are valid.
+ */
+ public PNGHeader(int width, int height, int depth,
+ int colorType, boolean interlace)
+ {
+ super( TYPE_HEADER );
+ data = new byte[ 13 ];
+
+ this.width = width;
+ this.height = height;
+ this.depth = depth;
+ compression = filter = 0;
+ this.colorType = colorType;
+ this.interlace = interlace ? 1 : 0;
+
+ // Build the data chunk.
+ byte[] a = getInt( width );
+ byte[] b = getInt( height );
+ data[0] = a[0]; data[1] = a[1]; data[2] = a[2]; data[3] = a[3];
+ data[4] = b[0]; data[5] = b[1]; data[6] = b[2]; data[7] = b[3];
+ data[8] = (byte)depth;
+ data[9] = (byte)colorType;
+ data[10] = (byte)compression;
+ data[11] = (byte)filter;
+ data[12] = (byte)this.interlace;
+ }
+
+ /**
+ * Validates the header fields
+ */
+ public boolean isValidChunk()
+ {
+ if( !super.isValidChunk() )
+ return false;
+
+ // width and height must be nonzero
+ if( width == 0 || height == 0 )
+ return false;
+ // colorType can be 0,2,3,4,6
+ if( (colorType & 0xFFFFFFF8) != 0 || colorType == 5 || colorType == 1)
+ return false;
+ // Possible valid depths are 1,2,4,8,16
+ if( !((depth == 1) || (depth == 2) || (depth == 4) ||
+ (depth == 8) || (depth == 16)) )
+ return false;
+ if( colorType == INDEXED && depth == 16 )
+ return false;
+ if( ( colorType == RGB || colorType == GRAYSCALE_WITH_ALPHA ||
+ colorType == RGB_WITH_ALPHA ) &&
+ depth < 8 )
+ return false;
+ // Only compression and filter methods zero are defined
+ if( compression != 0 || filter != 0 )
+ return false;
+ // Interlace methods, 0 and 1 are valid values.
+ if( (interlace & 0xFFFFFFFE) != 0 )
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Returns <code>true</code> if this PNG is indexed-color
+ */
+ public boolean isIndexed()
+ {
+ return (colorType == INDEXED);
+ }
+
+ /**
+ * Returns <code>true</code> if this PNG is grayscale
+ */
+ public boolean isGrayscale()
+ {
+ return ((colorType == GRAYSCALE) || (colorType == GRAYSCALE_WITH_ALPHA));
+ }
+
+ /**
+ * Returns the color type of the image.
+ */
+ public int getColorType()
+ {
+ return colorType;
+ }
+
+ /**
+ * Returns whether the image is interlaced or not.
+ */
+ public boolean isInterlaced()
+ {
+ return (interlace != 0);
+ }
+
+ /**
+ * Returns the number of bytes per pixel.
+ */
+ public int bytesPerPixel()
+ {
+ switch( colorType )
+ {
+ case GRAYSCALE_WITH_ALPHA:
+ return ((depth * 2) >> 3);
+ case RGB:
+ return ((depth * 3) >> 3);
+ case RGB_WITH_ALPHA:
+ return ((depth * 4) >> 3);
+
+ default:
+ case GRAYSCALE:
+ case INDEXED:
+ int i = (depth >> 3);
+ if( i > 0 ) return i;
+ return 1; // if bytes per pixel < 1, return 1 anyway.
+ }
+ }
+
+ /**
+ * Returns the stride of one scanline, in bytes.
+ */
+ public int getScanlineStride()
+ {
+ long nBits = 0; // bits per scanline - scanlines are on byte offsets.
+ switch( colorType )
+ {
+ case GRAYSCALE:
+ nBits = width * depth;
+ break;
+ case RGB:
+ nBits = width * depth * 3;
+ break;
+ case INDEXED:
+ nBits = depth * width;
+ break;
+ case GRAYSCALE_WITH_ALPHA:
+ nBits = depth * width * 2;
+ break;
+ case RGB_WITH_ALPHA:
+ nBits = depth * width * 4;
+ break;
+ }
+ // Round up number of bits to the nearest byte
+ if( (nBits & 0x07) != 0 )
+ nBits += (8 - (nBits & 0x07));
+
+ return (int)(nBits >> 3); // return # of bytes.
+ }
+
+ public int getWidth()
+ {
+ return width;
+ }
+
+ public int getHeight()
+ {
+ return height;
+ }
+
+ public int getDepth()
+ {
+ return depth;
+ }
+
+ /**
+ * Debugging string.
+ */
+ public String toString()
+ {
+ return "Header Chunk. Image width:"+width+" height:"+height+
+ " depth:"+depth+" color type:"+colorType+" compression type:"+
+ compression+" filter type:"+ filter+" interlace:"+interlace;
+ }
+}
diff --git a/gnu/javax/imageio/png/PNGICCProfile.java b/gnu/javax/imageio/png/PNGICCProfile.java
new file mode 100644
index 000000000..d2696e1c6
--- /dev/null
+++ b/gnu/javax/imageio/png/PNGICCProfile.java
@@ -0,0 +1,114 @@
+/* PNGICCProfile.java --
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.png;
+
+import java.awt.color.ICC_Profile;
+import java.awt.color.ICC_ColorSpace;
+import java.awt.color.ColorSpace;
+import java.io.UnsupportedEncodingException;
+import java.io.IOException;
+import java.io.ByteArrayInputStream;
+import java.util.zip.InflaterInputStream;
+import java.util.zip.Deflater;
+
+/**
+ * A PNG iCCP (ICC Profile) chunk.
+ */
+public class PNGICCProfile extends PNGChunk
+{
+ private String name;
+ private ICC_Profile profile;
+ // A generic profile name to use "ICC Profile"
+ private static final byte[] genericName = new byte[]
+ { 0x49, 0x43, 0x43, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65 };
+
+ protected PNGICCProfile( int type, byte[] data, int crc ) throws PNGException
+ {
+ super( type, data, crc );
+ int i = 0;
+ while( data[i++] != 0 );
+ try
+ {
+ name = new String(data, 0, i, "8859_1");
+ }
+ catch(UnsupportedEncodingException e)
+ {
+ name = ""; // shouldn't really happen.
+ }
+ if( data[i++] != 0 )
+ throw new PNGException("Can't handle nonzero compression types with iCCP chunks.");
+ try
+ {
+ ByteArrayInputStream bos = new ByteArrayInputStream( data, i,
+ data.length - i );
+ profile = ICC_Profile.getInstance( new InflaterInputStream( bos ) );
+ }
+ catch(IOException ioe)
+ {
+ throw new PNGException("Couldn't read iCCP profile chunk.");
+ }
+ System.out.println("Got profile:"+profile);
+ }
+
+ public PNGICCProfile( ICC_Profile profile )
+ {
+ super( TYPE_PROFILE );
+ this.profile = profile;
+ byte[] profData = profile.getData();
+ byte[] outData = new byte[ profData.length * 2 ];
+ Deflater deflater = new Deflater();
+ deflater.setInput( profData );
+ deflater.finish();
+ int n = deflater.deflate( outData );
+ data = new byte[ n + 11 + 2 ];
+ System.arraycopy(genericName, 0, data, 0, 11 );
+ data[11] = data[12] = 0; // null separator and compression type.
+ // Copy compressed data
+ System.arraycopy(outData, 0, data, 13, n );
+ }
+
+ public ColorSpace getColorSpace()
+ {
+ return new ICC_ColorSpace( profile );
+ }
+
+ public String toString()
+ {
+ return "PNG ICC Profile, name: "+name;
+ }
+}
diff --git a/gnu/javax/imageio/png/PNGImageReader.java b/gnu/javax/imageio/png/PNGImageReader.java
new file mode 100644
index 000000000..64aa3fea5
--- /dev/null
+++ b/gnu/javax/imageio/png/PNGImageReader.java
@@ -0,0 +1,224 @@
+/* PNGImageReader.java -- The ImageIO ImageReader for PNG
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.imageio.png;
+
+import gnu.javax.imageio.IIOInputStream;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import javax.imageio.ImageReadParam;
+import javax.imageio.ImageReader;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.stream.ImageInputStream;
+
+/**
+ * The ImageIO ImageReader for PNG images.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class PNGImageReader
+ extends ImageReader
+{
+
+ /**
+ * The PNG file.
+ */
+ private PNGFile pngFile;
+
+ /**
+ * The decoded image.
+ */
+ private BufferedImage image;
+
+ /**
+ * The supported image types for PNG.
+ */
+ private ArrayList imageTypes;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param spi the corresponding ImageReaderSpi
+ */
+ public PNGImageReader(PNGImageReaderSpi spi)
+ {
+ super(spi);
+ }
+
+ /**
+ * Returns the height of the image.
+ */
+ public int getHeight(int imageIndex)
+ throws IOException
+ {
+ checkIndex(imageIndex);
+ readImage();
+ return image.getHeight();
+ }
+
+ /**
+ * Returns the width of the image.
+ *
+ * @param imageIndex the index of the image
+ *
+ * @return the width of the image
+ */
+ public int getWidth(int imageIndex) throws IOException
+ {
+ checkIndex(imageIndex);
+ readImage();
+ return image.getWidth();
+ }
+
+ /**
+ * Returns the image types for the image.
+ *
+ * @see ImageReader#getImageTypes(int)
+ */
+ public Iterator getImageTypes(int imageIndex)
+ throws IOException
+ {
+ checkIndex(imageIndex);
+ readImage();
+ if (imageTypes == null)
+ {
+ imageTypes = new ArrayList();
+ imageTypes.add(new ImageTypeSpecifier(image.getColorModel(),
+ image.getSampleModel()));
+ }
+ return imageTypes.iterator();
+ }
+
+ /**
+ * Returns the number of images in the stream.
+ *
+ * @return the number of images in the stream
+ *
+ * @see ImageReader#getNumImages(boolean)
+ */
+ public int getNumImages(boolean allowSearch)
+ throws IOException
+ {
+ return 1;
+ }
+
+ /**
+ * Reads the image.
+ *
+ * @param imageIndex the index of the image to read
+ * @param param additional parameters
+ */
+ public BufferedImage read(int imageIndex, ImageReadParam param)
+ throws IOException
+ {
+ checkIndex(imageIndex);
+ readImage();
+ return image;
+ }
+
+ /**
+ * Sets the input and checks the input parameter.
+ *
+ * @see ImageReader#setInput(Object, boolean, boolean)
+ */
+ public void setInput(Object input,
+ boolean seekForwardOnly,
+ boolean ignoreMetadata)
+ {
+ super.setInput(input, seekForwardOnly, ignoreMetadata);
+ if (! (input instanceof InputStream || input instanceof ImageInputStream))
+ throw new IllegalArgumentException("Input not an ImageInputStream");
+ }
+
+ public IIOMetadata getImageMetadata(int imageIndex)
+ throws IOException
+ {
+ // TODO: Not (yet) supported.
+ checkIndex(imageIndex);
+ return null;
+ }
+
+ public IIOMetadata getStreamMetadata()
+ throws IOException
+ {
+ // TODO: Not (yet) supported.
+ return null;
+ }
+
+ /**
+ * Checks the image indexa and throws and IndexOutOfBoundsException if
+ * appropriate.
+ *
+ * @param index the index to check
+ */
+ private void checkIndex(int index)
+ {
+ if (index > 0)
+ throw new IndexOutOfBoundsException("Image index out of bounds");
+ }
+
+ /**
+ * Makes sure that the image is read.
+ *
+ * @throws IOException if something goes wrong
+ */
+ private void readImage()
+ throws IOException
+ {
+ if (pngFile == null)
+ {
+ if (input instanceof InputStream)
+ pngFile = new PNGFile((InputStream) input);
+ else if (input instanceof ImageInputStream)
+ pngFile = new PNGFile(new IIOInputStream((ImageInputStream) input));
+ else
+ assert false : "Must not happen";
+ }
+
+ if (pngFile != null && image == null)
+ {
+ image = pngFile.getBufferedImage();
+ }
+ }
+}
diff --git a/gnu/javax/imageio/png/PNGImageReaderSpi.java b/gnu/javax/imageio/png/PNGImageReaderSpi.java
new file mode 100644
index 000000000..0092ab558
--- /dev/null
+++ b/gnu/javax/imageio/png/PNGImageReaderSpi.java
@@ -0,0 +1,128 @@
+/* PNGImageReaderSpi.java -- The ImageReader service provider for PNG
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.imageio.png;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Locale;
+
+import javax.imageio.ImageReader;
+import javax.imageio.spi.ImageReaderSpi;
+import javax.imageio.stream.ImageInputStream;
+
+/**
+ * The ImageIO ImageReader service provider for PNG images.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class PNGImageReaderSpi
+ extends ImageReaderSpi
+{
+
+ /**
+ * The PNG file signature.
+ */
+ private static final byte[] SIGNATURE = new byte[]
+ { (byte) 137, 80, 78, 71, 13, 10, 26, 10 };
+
+ private static final String VENDOR_NAME = "GNU";
+ static final String VERSION = "1.0";
+ static final String READER_CLASSNAME =
+ "gnu.javax.imageio.png.PNGImageReader";
+ static final String[] NAMES = { "Portable Network Graphics" };
+ static final String[] SUFFIXES = { ".png" , ".PNG" };
+ static final String[] MIME_TYPES = { "image/png" };
+ static final String[] WRITER_SPI_NAMES =
+ new String[] { "gnu.javax.imageio.png.PNGWriterSpi" };
+ static final Class[] INPUT_TYPES = new Class[]{ InputStream.class,
+ ImageInputStream.class};
+ public PNGImageReaderSpi()
+ {
+ super(VENDOR_NAME, VERSION, NAMES, SUFFIXES, MIME_TYPES, READER_CLASSNAME,
+ INPUT_TYPES, WRITER_SPI_NAMES, false, null, null, null, null, false,
+ null, null, null, null);
+ }
+
+ /**
+ * Determines if the PNG ImageReader can decode the specified input.
+ *
+ * @param source the source to decode
+ */
+ public boolean canDecodeInput(Object source) throws IOException
+ {
+ boolean canDecode = false;
+ if (source instanceof ImageInputStream)
+ {
+ ImageInputStream in = (ImageInputStream) source;
+ in.mark();
+ canDecode = true;
+ for (int i = 0; i < SIGNATURE.length && canDecode; i++)
+ {
+ byte sig = (byte) in.read();
+ if (sig != SIGNATURE[i]) {
+ canDecode = false;
+ }
+ }
+ in.reset();
+ }
+ return canDecode;
+ }
+
+ /**
+ * Returns a new PNGImageReader instance.
+ *
+ * @param extension the extension, ignored
+ */
+ public ImageReader createReaderInstance(Object extension)
+ throws IOException
+ {
+ return new PNGImageReader(this);
+ }
+
+ /**
+ * Returns a description.
+ *
+ * @param locale the locale
+ */
+ public String getDescription(Locale locale)
+ {
+ return "Portable Network Graphics";
+ }
+
+}
diff --git a/gnu/javax/imageio/png/PNGPalette.java b/gnu/javax/imageio/png/PNGPalette.java
new file mode 100644
index 000000000..478129df5
--- /dev/null
+++ b/gnu/javax/imageio/png/PNGPalette.java
@@ -0,0 +1,127 @@
+/* PNGPalette.java --
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.png;
+
+import java.awt.color.ColorSpace;
+import java.awt.image.IndexColorModel;
+
+/**
+ * A PNG Palette chunk.
+ */
+public class PNGPalette extends PNGChunk
+{
+ private int[] red,green,blue;
+
+ protected PNGPalette( int type, byte[] data, int crc ) throws PNGException
+ {
+ super( type, data, crc );
+ double l = data.length;
+ l /= 3.0;
+ // Check if it's divisible by 3. (Yuck.)
+ if( l - Math.floor(l) != 0.0 )
+ throw new PNGException("Invalid size of palette chunk.");
+ int nEntries = (int)l;
+
+ red = new int[ nEntries ];
+ green = new int[ nEntries ];
+ blue = new int[ nEntries ];
+ for( int i = 0; i < nEntries; i++ )
+ {
+ red[i] = (data[ i * 3 ] & 0xFF);
+ green[i] = (data[ i * 3 + 1 ] & 0xFF);
+ blue[i] = (data[ i * 3 + 2] & 0xFF);
+ }
+ }
+
+ public PNGPalette( IndexColorModel cm )
+ {
+ super( TYPE_PALETTE );
+ int n = cm.getMapSize();
+ data = new byte[ n * 3 ];
+ red = new int[ n ];
+ green = new int[ n ];
+ blue = new int[ n ];
+ for(int i = 0; i < n; i++ )
+ {
+ red[i] = data[i * 3] = (byte)cm.getRed(i);
+ green[i] = data[i * 3 + 1] = (byte)cm.getGreen(i);
+ blue[i] = data[i * 3 + 2] = (byte)cm.getBlue(i);
+ }
+ }
+
+ public IndexColorModel getPalette( ColorSpace cs )
+ {
+ int nc = red.length;
+ byte[] r = new byte[nc];
+ byte[] g = new byte[nc];
+ byte[] b = new byte[nc];
+
+ if( cs == null )
+ {
+ for(int i = 0; i < nc; i ++ )
+ {
+ r[i] = (byte)red[i];
+ g[i] = (byte)green[i];
+ b[i] = (byte)blue[i];
+ }
+ }
+ else
+ {
+ for(int i = 0; i < nc; i ++ )
+ {
+ float[] in = new float[3];
+ in[0] = (((float)red[i]) / 255f);
+ in[1] = (((float)green[i]) / 255f);
+ in[2] = (((float)blue[i]) / 255f);
+ float[] out = cs.toRGB( in );
+ r[i] = (byte)( Math.round(out[0] * 255.0) );
+ g[i] = (byte)( Math.round(out[1] * 255.0) );
+ b[i] = (byte)( Math.round(out[2] * 255.0) );
+ }
+ }
+ return new IndexColorModel(8, nc, r, g, b);
+ }
+
+ public String toString()
+ {
+ String s = "PNG Palette:\n";
+ for( int i = 0; i < red.length; i++)
+ s = s + "Index " + i + ": ["+ red[i] +", "+green[i]+", "+blue[i]+"]\n";
+ return s;
+ }
+}
diff --git a/gnu/javax/imageio/png/PNGPhys.java b/gnu/javax/imageio/png/PNGPhys.java
new file mode 100644
index 000000000..0a82d6acb
--- /dev/null
+++ b/gnu/javax/imageio/png/PNGPhys.java
@@ -0,0 +1,112 @@
+/* PNGPhys.java --
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.png;
+
+/**
+ * A PNG "pHYS" chunk - pixel physical dimensions
+ */
+public class PNGPhys extends PNGChunk
+{
+ long x, y;
+ double ratio;
+ boolean usesRatio;
+
+ protected PNGPhys( int type, byte[] data, int crc ) throws PNGException
+ {
+ super( type, data, crc );
+ if( data.length < 9 )
+ throw new PNGException("Unexpected size of pHYS chunk.");
+ x = ((data[0] & 0xFF) << 24) | ( (data[1] & 0xFF) << 16 ) |
+ ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
+ y = ((data[4] & 0xFF) << 24) | ( (data[5] & 0xFF) << 16 ) |
+ ((data[6] & 0xFF) << 8) | (data[7] & 0xFF);
+ if(data[8] == 0)
+ {
+ ratio = ((double)x)/((double)y);
+ usesRatio = true;
+ }
+ }
+
+ public PNGPhys( double ratio )
+ {
+ super( TYPE_PHYS );
+
+ this.ratio = ratio;
+ usesRatio = true;
+
+ if( ratio < 1.0 )
+ {
+ y = 0xFFFFFFFF;
+ x = (long)(0xFFFFFFFFL * ratio);
+ }
+ else
+ {
+ x = 0xFFFFFFFF;
+ y = (long)(0xFFFFFFFFL * ratio);
+ }
+ makeData();
+ }
+
+ public PNGPhys( int x, int y )
+ {
+ super( TYPE_PHYS );
+ usesRatio = false;
+ this.x = x;
+ this.y = y;
+ makeData();
+ }
+
+ private void makeData()
+ {
+ data = new byte[ 9 ];
+ byte[] a = getInt( (int)x );
+ byte[] b = getInt( (int)y );
+ data[0] = a[0]; data[1] = a[1]; data[2] = a[2]; data[3] = a[3];
+ data[4] = b[0]; data[5] = b[1]; data[6] = b[2]; data[7] = b[3];
+ data[7] = (usesRatio) ? 0 : (byte)0xFF;
+ }
+
+ public String toString()
+ {
+ String s = "PNG Physical pixel size chunk.";
+ if( usesRatio )
+ return s + " Aspect ratio (x/y): " + ratio;
+ else
+ return s + " " + x + " by " + y + " pixels per meter. (x, y).";
+ }
+}
diff --git a/gnu/javax/imageio/png/PNGTime.java b/gnu/javax/imageio/png/PNGTime.java
new file mode 100644
index 000000000..9b5c0332a
--- /dev/null
+++ b/gnu/javax/imageio/png/PNGTime.java
@@ -0,0 +1,83 @@
+/* PNGTime.java --
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.imageio.png;
+
+import java.util.Date;
+
+/**
+ * A PNG tIME chunk.
+ */
+public class PNGTime extends PNGChunk
+{
+ private Date date;
+
+ protected PNGTime( int type, byte[] data, int crc ) throws PNGException
+ {
+ super( type, data, crc );
+ if( data.length < 7 )
+ throw new PNGException("Unexpectedly short time chunk. ("+data.length+" bytes)");
+
+ // PNG value is absolute (2006, not 106 or 06), java is from 1900.
+ int year = ( (data[0] & 0xFF) << 8 ) | (data[1] & 0xFF);
+ int month = (data[2] & 0xFF); // java counts from 0. PNG from 1.
+ int day = (data[3] & 0xFF);
+ int hour = (data[4] & 0xFF);
+ int minute = (data[5] & 0xFF);
+ int second = (data[6] & 0xFF);
+ date = new Date( year - 1900, month - 1, day, hour, minute, second );
+ }
+
+ public PNGTime( Date d )
+ {
+ super( TYPE_TIME );
+ data = new byte[ 7 ];
+ int tmp = d.getYear() + 1900;
+ data[0] = (byte)((tmp & 0xFF00) >> 8);
+ data[1] = (byte)(tmp & 0x00FF);
+ data[2] = (byte)(d.getMonth() + 1);
+ data[3] = (byte)(d.getDay());
+ data[4] = (byte)(d.getHours());
+ data[5] = (byte)(d.getMinutes());
+ data[6] = (byte)(d.getSeconds());
+ }
+
+ public String toString()
+ {
+ return "PNG Time chunk: "+date;
+ }
+}
diff --git a/gnu/javax/naming/giop/ContextContinuation.java b/gnu/javax/naming/giop/ContextContinuation.java
new file mode 100644
index 000000000..7d7a785fd
--- /dev/null
+++ b/gnu/javax/naming/giop/ContextContinuation.java
@@ -0,0 +1,956 @@
+/* ContextContinuation.java -- handles corbaname: urls
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.naming.giop;
+
+import gnu.CORBA.NamingService.Ext;
+import gnu.CORBA.NamingService.NameTransformer;
+
+import java.util.Hashtable;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.ContextNotEmptyException;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NameClassPair;
+import javax.naming.NameNotFoundException;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.OperationNotSupportedException;
+import javax.naming.directory.InvalidAttributesException;
+
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.portable.Delegate;
+import org.omg.CORBA.portable.ObjectImpl;
+import org.omg.CosNaming.BindingIteratorHolder;
+import org.omg.CosNaming.BindingListHolder;
+import org.omg.CosNaming.NameComponent;
+import org.omg.CosNaming.NamingContext;
+import org.omg.CosNaming.NamingContextExt;
+import org.omg.CosNaming.NamingContextExtHelper;
+import org.omg.CosNaming.NamingContextHelper;
+import org.omg.CosNaming._NamingContextExtStub;
+import org.omg.CosNaming._NamingContextStub;
+import org.omg.CosNaming.NamingContextPackage.AlreadyBound;
+import org.omg.CosNaming.NamingContextPackage.CannotProceed;
+import org.omg.CosNaming.NamingContextPackage.InvalidName;
+import org.omg.CosNaming.NamingContextPackage.NotFound;
+
+/**
+ * The context to represent the corba naming service. Being the naming service,
+ * the returned context supports creating the subcontexts, forwarding this task
+ * to the existing naming service. When listing bindings, it uses the
+ * {@link Context#BATCHSIZE} property to determine, how many bindings should
+ * be returned at once (the process is transparend)
+ *
+ * @author Audrius Meskauskas (audriusa@Bioinformatics.org)
+ */
+public class ContextContinuation implements Context
+{
+ /**
+ * This number of bindings will be requested from the naming server at once,
+ * while the subsequent bindings will be requested via binding iterator one by
+ * one. Use {@link Context#BATCHSIZE} to override the value of this constant.
+ */
+ public int DEFAULT_BATCH_SIZE = 20;
+
+ /**
+ * The actual CORBA naming service.
+ */
+ NamingContextExt service;
+
+ /**
+ * The object request broker, used to access the naming service. This field
+ * is only initialised when the context is constructed from the URL.
+ */
+ ORB orb;
+
+ /**
+ * The properties.
+ */
+ Hashtable properties;
+
+ /**
+ * The parent factory.
+ */
+ GiopNamingServiceFactory factory;
+
+ /**
+ * The name transformer to obtain the name from its string representation. The
+ * to_name method of the naming service is avoided as it may be remote and
+ * hence expensive. The conversion rules are standard and cannot be service
+ * specific.
+ */
+ static NameTransformer transformer = new NameTransformer();
+
+ /**
+ * The batch size for list operations - how many to return at once.
+ */
+ public final int howMany;
+
+ /**
+ * Creates a new naming context that uses naming service, represented by the
+ * given CORBA object.
+ *
+ * @param namingService
+ * the naming service object. It must be possible to narrow it into
+ * the NamingContextExt.
+ * @param props
+ * the environment table.
+ * @param orb
+ * the associated ORB. This reference is used during cleanup.
+ * @param the
+ * parent factory. This reference is used during cleanup.
+ */
+ public ContextContinuation(org.omg.CORBA.Object nsObject,
+ Hashtable props, ORB anOrb,
+ GiopNamingServiceFactory aFactory)
+ {
+ factory = aFactory;
+ orb = anOrb;
+
+ Delegate delegate = ((ObjectImpl) nsObject)._get_delegate();
+
+ // If the IOR provides the IDL ID, we can check if our name
+ // service is old NamingContext or new NamingContextExt.
+ // Not all forms of the URL always provide the IDL id.
+ if (!nsObject._is_a(NamingContextExtHelper.id())
+ && nsObject._is_a(NamingContextHelper.id()))
+ {
+ // We are surely working with the old version.
+ _NamingContextStub stub = new _NamingContextStub();
+ stub._set_delegate(delegate);
+ // The Ext object will add the necessary extensions.
+ service = new Ext(stub);
+ }
+ else
+ {
+ // We expecte the service to be the NamingContextExt (this is true
+ // for both Sun's and our implementations). There is no easy way
+ // to check the version.
+ _NamingContextExtStub stub = new _NamingContextExtStub();
+ stub._set_delegate(delegate);
+ service = stub;
+ }
+ properties = props;
+ howMany = getBatchSize();
+ }
+
+ /**
+ * Give the specified name for the specified object. The passed name must not
+ * be already bound to some other object. The components of the name are
+ * mapped into the components of the CORBA name.
+ *
+ * @param name
+ * the name that will be given to the object (in the scope of this
+ * context).
+ * @param obj
+ * the object being named.
+ * @throws NameAlreadyBoundException
+ * if this name is already used to name some object.
+ * @throws InvalidAttributesException
+ * if the object does not supply all required attributes.
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void bind(Name name, Object obj) throws NamingException
+ {
+ try
+ {
+ org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
+ service.bind(toGiop(name), object);
+ }
+ catch (ClassCastException e)
+ {
+ throw new NamingException(org.omg.CORBA.Object.class + " required ");
+ }
+ catch (InvalidName e)
+ {
+ throw new InvalidNameException();
+ }
+ catch (AlreadyBound e)
+ {
+ throw new NameAlreadyBoundException();
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ /**
+ * Give the specified name for the specified object. The passed name must not
+ * be already bound to some other object.
+ *
+ * @param name
+ * the name that will be given to the object (in the scope of this
+ * context).
+ * @param obj
+ * the object being named.
+ * @throws NameAlreadyBoundException
+ * if this name is already used to name some object.
+ * @throws InvalidAttributesException
+ * if the object does not supply all required attributes.
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void bind(String name, Object obj) throws NamingException
+ {
+ try
+ {
+ org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
+ service.bind(transformer.toName(name), object);
+ }
+ catch (ClassCastException e)
+ {
+ throw new NamingException(org.omg.CORBA.Object.class + " required ");
+ }
+ catch (InvalidName e)
+ {
+ throw new InvalidNameException();
+ }
+ catch (AlreadyBound e)
+ {
+ throw new NameAlreadyBoundException();
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ /**
+ * Releases all resources, associated with this context. The close() method
+ * can be called several times, but after it has been once invoked, it is not
+ * allowed to call any other method of this context. This method destroys
+ * the ORB, if we have one.
+ *
+ * @throws NamingException
+ */
+ public void close() throws NamingException
+ {
+ if (orb != null && factory !=null)
+ {
+ factory.checkIfReferenced(orb);
+ }
+ }
+
+ /**
+ * Not supported.
+ */
+ public Name composeName(Name name, Name prefix) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Not supported
+ */
+ public String composeName(String name1, String name2) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Creates the new naming subcontext and binds it to the current (this)
+ * context. The returned object will wrap around the newly created CORBA
+ * subcontext
+ *
+ * @param name
+ * the name of the new context being created
+ * @return the newly created context, bound to the instance of the context on
+ * that the method has been called
+ * @throws NameAlreadyBoundException
+ * if this name is already bound
+ * @throws InvalidAttributesException
+ * if the creation of the new context requires the missing mandatory
+ * attributes
+ * @throws NamingException
+ */
+ public Context createSubcontext(Name subContext) throws NamingException
+ {
+ try
+ {
+ org.omg.CORBA.Object subcontext = service.bind_new_context(
+ toGiop(subContext));
+ Hashtable clonedProps = new Hashtable();
+ clonedProps.putAll(properties);
+
+ // Nulls are passed both for orb and factory, as the child contexts
+ // need not to do any cleanup.
+ return new ContextContinuation(subcontext, clonedProps, null, null);
+ }
+ catch (AlreadyBound e)
+ {
+ throw new NameAlreadyBoundException();
+ }
+ catch (InvalidName e)
+ {
+ throw new InvalidNameException();
+ }
+ catch (Exception ex)
+ {
+ throw new NamingException(ex.toString());
+ }
+ }
+
+ /**
+ * Creates the new naming subcontext and binds it to the current (this)
+ * context. The returned object will wrap around the newly created CORBA
+ * subcontext
+ *
+ * @param name
+ * the name of the new context being created
+ * @return the newly created context, bound to the instance of the context on
+ * that the method has been called
+ * @throws NameAlreadyBoundException
+ * if this name is already bound
+ * @throws InvalidAttributesException
+ * if the creation of the new context requires the missing mandatory
+ * attributes
+ * @throws NamingException
+ */
+ public Context createSubcontext(String subContext) throws NamingException
+ {
+ try
+ {
+ org.omg.CORBA.Object subcontext =
+ service.bind_new_context(transformer.toName(subContext));
+ Hashtable clonedProps = new Hashtable();
+ clonedProps.putAll(properties);
+
+ // Nulls are passed both for orb and factory, as the child contexts
+ // need not to do any cleanup.
+ return new ContextContinuation(subcontext, clonedProps, null,
+ null);
+ }
+ catch (AlreadyBound e)
+ {
+ throw new NameAlreadyBoundException(subContext);
+ }
+ catch (InvalidName e)
+ {
+ throw new InvalidNameException(subContext);
+ }
+ catch (Exception ex)
+ {
+ throw new NamingException(ex.toString());
+ }
+ }
+
+ /**
+ * Removes the naming subcontext from this naming context. Returns without
+ * action if such subcontext does not exist. The context being destroyed must
+ * be empty.
+ *
+ * @param name
+ * the name of the subcontext beig removed.
+ * @throws ContextNotEmptyException
+ * if the named context is not empty.
+ * @throws NamingException
+ */
+ public void destroySubcontext(Name subContext) throws NamingException
+ {
+ unbind(subContext);
+ }
+
+ /**
+ * Removes the naming subcontext from this naming context. Returns without
+ * action if such subcontext does not exist. The context being destroyed must
+ * be empty.
+ *
+ * @param name
+ * the name of the subcontext beig removed.
+ * @throws ContextNotEmptyException
+ * if the named context is not empty.
+ * @throws NamingException
+ */
+ public void destroySubcontext(String subContext) throws NamingException
+ {
+ unbind(subContext);
+ }
+
+ /**
+ * Returs the full name of this naming context. The returned string is not a
+ * JNDI composite name and should not be passed directly to the methods of the
+ * naming context. This implementation returns the IOR.
+ *
+ * @return the full name of this naming context, in its own namespace.
+ * @throws OperationNotSupportedException
+ * if the naming system, represented by this context, does not
+ * support the notation of the full name.
+ * @throws NamingException
+ */
+ public String getNameInNamespace() throws NamingException
+ {
+ if (orb != null)
+ return orb.object_to_string(service);
+ else
+ {
+ try
+ {
+ ObjectImpl impl = (ObjectImpl) service;
+ return impl._orb().object_to_string(impl);
+ }
+ catch (ClassCastException e)
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+ }
+
+ /**
+ * Not supported.
+ */
+ public NameParser getNameParser(Name name) throws NamingException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Not supported.
+ */
+ public NameParser getNameParser(String name) throws NamingException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Creates and returns the enumeration over the name bindings that are present
+ * the given subcontext. The enumeration elements have the type of
+ * {@link NameClassPair}, providing also information about the class of the
+ * bound object. The behaviour in the case if the bindings are added or
+ * removed later is not defined. The contents of the subcontexts are not
+ * included.
+ *
+ * @param name
+ * the name of the subcontext
+ * @return the enumeration over the names, known for the given subcontext.
+ * @throws NamingException
+ */
+ public NamingEnumeration list(Name name) throws NamingException
+ {
+ BindingIteratorHolder bi = new BindingIteratorHolder();
+ BindingListHolder bl = new BindingListHolder();
+
+ NamingContext subcontext;
+
+ if (name.size() == 0)
+ subcontext = service;
+ else
+ {
+ try
+ {
+ subcontext = (NamingContextHelper.narrow(service.resolve(toGiop(name))));
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+
+ }
+
+ subcontext.list(howMany, bl, bi);
+
+ return new ListEnumeration(bl, bi, howMany);
+ }
+
+ /**
+ * Creates and returns the enumeration over the name bindings that are present
+ * the given subcontext. The enumeration elements have the type of
+ * {@link NameClassPair}, providing also information about the class of the
+ * bound object. The behaviour in the case if the bindings are added or
+ * removed later is not defined. The contents of the subcontexts are not
+ * included.
+ *
+ * @param name
+ * the name of the subcontext
+ * @return the enumeration over the names, known for the given subcontext.
+ * @throws NamingException
+ */
+ public NamingEnumeration list(String name) throws NamingException
+ {
+ BindingIteratorHolder bi = new BindingIteratorHolder();
+ BindingListHolder bl = new BindingListHolder();
+
+ NamingContext subcontext;
+
+ if (name.length() == 0)
+ subcontext = service;
+ else
+ {
+ try
+ {
+ subcontext = (NamingContextHelper.narrow(service.resolve_str(name)));
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+
+ }
+
+ subcontext.list(howMany, bl, bi);
+
+ return new ListEnumeration(bl, bi, howMany);
+ }
+
+ /**
+ * Creates and returns the enumeration over the name - object bindings that
+ * are present the given subcontext. The enumeration elements have the type of
+ * {@link Binding}, providing also information about the class of the bound
+ * object. The behaviour in the case if the bindings are added or removed
+ * later is not defined. The contents of the subcontexts are not included.
+ *
+ * @param name
+ * the name of the subcontext
+ * @return the enumeration over the names, known for the given subcontext.
+ * @throws NamingException
+ */
+ public NamingEnumeration listBindings(Name name) throws NamingException
+ {
+ BindingIteratorHolder bi = new BindingIteratorHolder();
+ BindingListHolder bl = new BindingListHolder();
+
+ NamingContext subcontext;
+
+ if (name.size() == 0)
+ subcontext = service;
+ else
+ {
+ try
+ {
+ subcontext = (NamingContextHelper.narrow(service.resolve(toGiop(name))));
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ subcontext.list(howMany, bl, bi);
+
+ return new ListBindingsEnumeration(bl, bi, howMany, subcontext);
+ }
+
+ /**
+ * Creates and returns the enumeration over the name - object bindings that
+ * are present the given subcontext. The enumeration elements have the type of
+ * {@link Binding}, providing also information about the class of the bound
+ * object. The behaviour in the case if the bindings are added or removed
+ * later is not defined. The contents of the subcontexts are not included.
+ *
+ * @param name
+ * the name of the subcontext
+ * @return the enumeration over the names, known for the given subcontext.
+ * @throws NamingException
+ */
+ public NamingEnumeration listBindings(String name) throws NamingException
+ {
+ BindingIteratorHolder bi = new BindingIteratorHolder();
+ BindingListHolder bl = new BindingListHolder();
+
+ NamingContext subcontext;
+
+ if (name.length() == 0)
+ subcontext = service;
+ else
+ {
+ try
+ {
+ subcontext = (NamingContextHelper.narrow(service.resolve_str(name)));
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+
+ }
+
+ subcontext.list(howMany, bl, bi);
+
+ return new ListBindingsEnumeration(bl, bi, howMany, subcontext);
+ }
+
+ /**
+ * Gets the previously named object by name. If the passed name is empty, the
+ * method should return a cloned instance of this naming context.
+ *
+ * @param name
+ * the name of the object being searched in this context
+ * @return the named object
+ * @throws NameNotFountException
+ * if the name is not found
+ */
+ public Object lookup(Name name) throws NamingException
+ {
+ try
+ {
+ return service.resolve(toGiop(name));
+ }
+ catch (NotFound e)
+ {
+ throw new NameNotFoundException();
+ }
+ catch (InvalidName e)
+ {
+ throw new InvalidNameException();
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ /**
+ * Gets the previously named object by name. If the passed name is empty, the
+ * method should return a cloned instance of this naming context.
+ *
+ * @param name
+ * the name of the object being searched in this context
+ * @return the named object
+ * @throws NamingException
+ * if the naming fails.
+ */
+ public Object lookup(String name) throws NamingException
+ {
+ try
+ {
+ return service.resolve_str(name);
+ }
+ catch (NotFound e)
+ {
+ throw new NameNotFoundException();
+ }
+ catch (InvalidName e)
+ {
+ throw new InvalidNameException();
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ /**
+ * Not supported.
+ */
+ public Object lookupLink(Name name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Not supported.
+ */
+ public Object lookupLink(String name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Give the specified name for the specified object. Unlike bind, this method
+ * silently replaces the existing binding for this name, if one exists.
+ *
+ * @param name
+ * the name that will be given to the object (in the scope of this
+ * context).
+ * @param obj
+ * the object being named.
+ * @throws InvalidAttributesException
+ * if the object does not supply all required attributes.
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void rebind(Name name, Object obj) throws NamingException
+ {
+ try
+ {
+ org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
+ service.rebind(toGiop(name), object);
+ }
+ catch (ClassCastException e)
+ {
+ throw new NamingException(org.omg.CORBA.Object.class + " required ");
+ }
+ catch (InvalidName e)
+ {
+ throw new InvalidNameException();
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ /**
+ * Give the specified name for the specified object. Unlike bind, this method
+ * silently replaces the existing binding for this name, if one exists.
+ *
+ * @param name
+ * the name that will be given to the object (in the scope of this
+ * context).
+ * @param obj
+ * the object being named.
+ * @throws InvalidAttributesException
+ * if the object does not supply all required attributes.
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void rebind(String name, Object obj) throws NamingException
+ {
+ try
+ {
+ org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
+ service.rebind(transformer.toName(name), object);
+ }
+ catch (ClassCastException e)
+ {
+ throw new NamingException(org.omg.CORBA.Object.class + " required ");
+ }
+ catch (InvalidName e)
+ {
+ throw new InvalidNameException();
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ /**
+ * Renames the existing binding, removing the existing and giving the new name
+ * for the same object.
+ *
+ * @param oldName
+ * the existing name of the known object
+ * @param newName
+ * the new name of the same object
+ * @throws NameNotFoundException
+ * if the oldName is unknown for this context
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void rename(Name oldName, Name newName) throws NamingException
+ {
+ Object object = lookup(oldName);
+ unbind(oldName);
+ bind(newName, object);
+ }
+
+ /**
+ * Renames the existing binding, removing the existing and giving the new name
+ * for the same object.
+ *
+ * @param oldName
+ * the existing name of the known object
+ * @param newName
+ * the new name of the same object
+ * @throws NameNotFoundException
+ * if the oldName is unknown for this context
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void rename(String oldName, String newName) throws NamingException
+ {
+ Object object = lookup(oldName);
+ unbind(oldName);
+ bind(newName, object);
+ }
+
+ /**
+ * Removes the name - object mapping from the current context. This method
+ * returns without action if the name is not bound to an object in the
+ * terminal context, but throws {@link NameNotFoundException} if one of the
+ * intermadiate contexts does not exist.
+ *
+ * @param name
+ * the name to be removed
+ * @throws NameNotFoundException
+ * if one of the intermediate naming contexts does not exist. Will
+ * not be thrown if just the terminal binding is missing.
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void unbind(Name name) throws NamingException
+ {
+ try
+ {
+ service.unbind(toGiop(name));
+ }
+ catch (NotFound e)
+ {
+ throw new NameNotFoundException();
+ }
+ catch (CannotProceed e)
+ {
+ throw new ContextNotEmptyException();
+ }
+ catch (InvalidName e)
+ {
+ throw new InvalidNameException();
+ }
+ }
+
+ /**
+ * Removes the name - object mapping from the current context. This method
+ * returns without action if the name is not bound to an object in the
+ * terminal context, but throws {@link NameNotFoundException} if one of the
+ * intermadiate contexts does not exist.
+ *
+ * @param name
+ * the name to be removed
+ * @throws NameNotFoundException
+ * if one of the intermediate naming contexts does not exist. Will
+ * not be thrown if just the terminal binding is missing.
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void unbind(String name) throws NamingException
+ {
+ try
+ {
+ service.unbind(transformer.toName(name));
+ }
+ catch (NotFound e)
+ {
+ throw new NameNotFoundException(name);
+ }
+ catch (CannotProceed e)
+ {
+ throw new ContextNotEmptyException(name);
+ }
+ catch (InvalidName e)
+ {
+ throw new InvalidNameException(name);
+ }
+ }
+
+ /**
+ * Add new environment property to the environment of this context. Both name
+ * and value of the new property must not be null. If the property is already
+ * defined, is current value is replaced by the propVal.
+ *
+ * @param propName
+ * the name of the new property
+ * @param propVal
+ * the value of the new property
+ * @return the previous value of this property or null if the property has not
+ * been previously defined
+ * @throws NamingException
+ */
+ public Object addToEnvironment(String key, Object value)
+ throws NamingException
+ {
+ if (key == null || value == null)
+ throw new NullPointerException();
+ return properties.put(key, value);
+ }
+
+ /**
+ * Returns the environment, associated with this naming context. The returned
+ * table should never be modified by the caller. Use {@link #addToEnvironment}
+ * and {@link #removeFromEnvironment} to modify the environement, if needed.
+ *
+ * @return the table, representing the environment of this context
+ * @throws NamingException
+ */
+ public Hashtable getEnvironment() throws NamingException
+ {
+ return properties;
+ }
+
+ /**
+ * Removes the property with the given name from the environment. Returns
+ * without action if this property is not defined.
+ *
+ * @param propName
+ * the name of the property being removed.
+ * @return the value of the property that has been removed or null if the
+ * property was not defined.
+ * @throws NamingException
+ */
+ public Object removeFromEnvironment(String propName) throws NamingException
+ {
+ return properties.remove(propName);
+ }
+
+ /**
+ * Convert the {@link Name} into array of the name components, required to the
+ * CORBA naming service. First the string representation is obtained, then
+ * it is converted using parsing rules of the CORBA name.
+ *
+ * @param name
+ * then name to convert
+ * @return the converted array of components.
+ */
+ public NameComponent[] toGiop(Name name) throws InvalidName
+ {
+ return transformer.toName(name.toString());
+ }
+
+ /**
+ * Get the batch size from the environment properties. The batch size is used
+ * for listing operations.
+ *
+ * @return the batch size, or some default value if not specified.
+ */
+ public int getBatchSize()
+ {
+ int batchSize = DEFAULT_BATCH_SIZE;
+ Object bs = properties.get(Context.BATCHSIZE);
+ if (bs != null)
+ {
+ try
+ {
+ int b = Integer.parseInt(bs.toString());
+ if (b >= 0)
+ batchSize = b;
+ }
+ catch (NumberFormatException e)
+ {
+ // OK, use default value.
+ }
+ }
+ return batchSize;
+ }
+
+
+}
diff --git a/gnu/javax/naming/giop/CorbalocParser.java b/gnu/javax/naming/giop/CorbalocParser.java
new file mode 100644
index 000000000..397b1c7d9
--- /dev/null
+++ b/gnu/javax/naming/giop/CorbalocParser.java
@@ -0,0 +1,439 @@
+/* CorbalocParser.java -- handles corbaname: urls
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.naming.giop;
+
+import gnu.CORBA.IOR;
+import gnu.CORBA.Minor;
+import gnu.CORBA.Unexpected;
+import gnu.CORBA.Version;
+import gnu.CORBA.NamingService.NameTransformer;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.StringTokenizer;
+
+import javax.naming.InvalidNameException;
+
+import org.omg.CORBA.BAD_PARAM;
+import org.omg.CORBA.DATA_CONVERSION;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.Object;
+import org.omg.CORBA.ORBPackage.InvalidName;
+
+/**
+ * Parses the alternative IOR representations into our IOR structure.
+ *
+ * TODO This parser currently supports only one address per target string. A
+ * string with the multiple addresses will be accepted, but only the last
+ * address will be taken into consideration. The fault tolerance is not yet
+ * implemented.
+ *
+ * The key string is filtered using {@link java.net.URLDecoder} that replaces
+ * the agreed escape sequences by the corresponding non alphanumeric characters.
+ *
+ * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
+ */
+public class CorbalocParser
+ extends NameTransformer
+{
+ /**
+ * The corbaloc prefix.
+ */
+ public static final String pxCORBALOC = "corbaloc";
+
+ /**
+ * The corbaname prefix.
+ */
+ public static final String pxCORBANAME = "corbaname";
+
+ /**
+ * The IOR prefix.
+ */
+ public static final String pxIOR = "ior";
+
+ /**
+ * The file:// prefix.
+ */
+ public static final String pxFILE = "file://";
+
+ /**
+ * The ftp:// prefix.
+ */
+ public static final String pxFTP = "ftp://";
+
+ /**
+ * The http:// prefix.
+ */
+ public static final String pxHTTP = "http://";
+
+ /**
+ * Marks iiop protocol.
+ */
+ public static final String IIOP = "iiop";
+
+ /**
+ * Marks rir protocol.
+ */
+ public static final String RIR = "rir";
+
+ /**
+ * The default port value, as specified in OMG documentation.
+ */
+ public static final int DEFAULT_PORT = 2809;
+
+ /**
+ * The default name.
+ */
+ public static final String DEFAULT_NAME = "NameService";
+
+ /**
+ * The string to name converter, initialized on demand.
+ */
+ static NameTransformer converter;
+
+ /**
+ * The current position.
+ */
+ int p;
+
+ /**
+ * The address being parsed, splitted into tokens.
+ */
+ String[] t;
+
+ /**
+ * Parse CORBALOC.
+ *
+ * The expected format is: <br>
+ * 1. corbaloc:[iiop][version.subversion@]:host[:port]/key <br>
+ * 2. corbaloc:rir:[/key] <br>
+ * 3. corbaname:[iiop][version.subversion@]:host[:port]/key <br>
+ * 4. corbaname:rir:[/key] <br>
+ * 5. file://[file name]<br>
+ * 6. http://[url]<br>
+ * 7. ftp://[url]<br>
+ *
+ * Protocol defaults to IOP, the object key defaults to the NameService.
+ *
+ * @param corbaloc the string to parse.
+ * @param orb the ORB, needed to create IORs and resolve rir references.
+ *
+ * @return the arrey of strings, first member being the IOR of the
+ * naming service, second member the name in the naming service.
+ */
+ public synchronized String[] corbaloc(String corbaloc,
+ ORB orb)
+ throws InvalidNameException
+ {
+ return corbaloc(corbaloc, orb, 0);
+ }
+
+ /**
+ * Parse controlling against the infinite recursion loop.
+ */
+ private String[] corbaloc(String corbaloc,
+ ORB orb, int recursion) throws InvalidNameException
+ {
+ // The used CORBA specification does not state how many times we should to
+ //redirect, but the infinite loop may be used to knock out the system.
+ // by malicious attempt.
+ if (recursion > 10)
+ throw new DATA_CONVERSION("More than 10 redirections");
+
+ if (corbaloc.startsWith(pxFILE))
+ return corbaloc(readFile(corbaloc.substring(pxFILE.length())), orb, recursion+1);
+ else if (corbaloc.startsWith(pxHTTP))
+ return corbaloc(readUrl(corbaloc), orb, recursion+1);
+ else if (corbaloc.startsWith(pxFTP))
+ return corbaloc(readUrl(corbaloc), orb, recursion+1);
+
+ // The version numbers with default values.
+ int major = 1;
+ int minor = 0;
+
+ // The host address.
+ String host;
+
+ // The port.
+ int port = DEFAULT_PORT;
+
+ // The object key as string.
+ String key;
+
+ StringTokenizer st = new StringTokenizer(corbaloc, ":@/.,#", true);
+
+ t = new String[st.countTokens()];
+
+ for (int i = 0; i < t.length; i++)
+ {
+ t[i] = st.nextToken();
+ }
+
+ p = 0;
+
+ if (!t[p].startsWith(pxCORBANAME))
+ throw new InvalidNameException(corbaloc+" must start with "+pxCORBANAME);
+
+ p++;
+
+ if (!t[p++].equals(":"))
+ throw new BAD_PARAM("Syntax (':' expected after name prefix)");
+
+ // Check for rir:
+ if (t[p].equals(RIR))
+ {
+ p++;
+ if (!t[p++].equals(":"))
+ throw new BAD_PARAM("':' expected after 'rir'");
+
+ key = readKey("/");
+
+ Object object;
+ try
+ {
+ object = orb.resolve_initial_references(key);
+ return resolve(orb.object_to_string(object));
+ }
+ catch (InvalidName e)
+ {
+ throw new BAD_PARAM("Unknown initial reference '" + key + "'");
+ }
+ }
+ else
+ // Check for iiop.
+ if (t[p].equals(IIOP) || t[p].equals(":"))
+ {
+ IOR ior = new IOR();
+
+ Addresses: do
+ { // Read addresses.
+ if (t[p].equals(":"))
+ {
+ p++;
+ }
+ else
+ {
+ p++;
+ if (!t[p++].equals(":"))
+ throw new BAD_PARAM("':' expected after 'iiop'");
+ // Check if version is present.
+ if (t[p + 1].equals("."))
+ if (t[p + 3].equals("@"))
+ {
+ // Version info present.
+ try
+ {
+ major = Integer.parseInt(t[p++]);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new BAD_PARAM("Major version number '"
+ + t[p - 1] + "'");
+ }
+ p++; // '.' at this point.
+ try
+ {
+ minor = Integer.parseInt(t[p++]);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new BAD_PARAM("Major version number '"
+ + t[p - 1] + "'");
+ }
+ p++; // '@' at this point.
+ }
+ }
+
+ ior.Internet.version = new Version(major, minor);
+
+ // Then host data goes till '/' or ':'.
+ StringBuffer bhost = new StringBuffer(corbaloc.length());
+ while (!t[p].equals(":") && !t[p].equals("/") && !t[p].equals(","))
+ bhost.append(t[p++]);
+
+ host = bhost.toString();
+
+ ior.Internet.host = host;
+
+ if (t[p].equals(":"))
+ {
+ // Port specified.
+ p++;
+ try
+ {
+ port = Integer.parseInt(t[p++]);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new BAD_PARAM("Invalid port '" + t[p - 1] + "'");
+ }
+ }
+
+ ior.Internet.port = port;
+
+ // Id is not listed.
+ ior.Id = "";
+
+ if (t[p].equals(","))
+ p++;
+ else
+ break Addresses;
+ }
+ while (true);
+
+ key = readKey("/");
+ ior.key = key.getBytes();
+
+ return resolve(ior.toStringifiedReference());
+ }
+
+ else
+ throw new InvalidNameException("Unsupported protocol '" + t[p] +
+ "' (iiop expected)");
+ }
+
+ /**
+ * Read IOR from the file in the local file system.
+ */
+ String readFile(String file)
+ {
+ File f = new File(file);
+ if (!f.exists())
+ {
+ DATA_CONVERSION err = new DATA_CONVERSION(f.getAbsolutePath()
+ + " does not exist.");
+ err.minor = Minor.Missing_IOR;
+ }
+ try
+ {
+ char[] c = new char[(int) f.length()];
+ FileReader fr = new FileReader(f);
+ fr.read(c);
+ fr.close();
+ return new String(c).trim();
+ }
+ catch (IOException ex)
+ {
+ DATA_CONVERSION d = new DATA_CONVERSION();
+ d.initCause(ex);
+ d.minor = Minor.Missing_IOR;
+ throw (d);
+ }
+ }
+
+ /**
+ * Read IOR from the remote URL.
+ */
+ String readUrl(String url)
+ {
+ URL u;
+ try
+ {
+ u = new URL(url);
+ }
+ catch (MalformedURLException mex)
+ {
+ throw new BAD_PARAM("Malformed URL: '" + url + "'");
+ }
+
+ try
+ {
+ InputStreamReader r = new InputStreamReader(u.openStream());
+
+ StringBuffer b = new StringBuffer();
+ int c;
+
+ while ((c = r.read()) > 0)
+ b.append((char) c);
+
+ return b.toString().trim();
+ }
+ catch (Exception exc)
+ {
+ DATA_CONVERSION d = new DATA_CONVERSION("Reading " + url + " failed.");
+ d.minor = Minor.Missing_IOR;
+ throw d;
+ }
+ }
+
+ private String[] resolve(String nsIor)
+ {
+ String [] n = new String[2];
+ n[0] = nsIor;
+ n[1] = readKey("#");
+ return n;
+ }
+
+ private String readKey(String delimiter)
+ throws BAD_PARAM
+ {
+ if (p < t.length)
+ if (!t[p].equals(delimiter))
+ {
+ if (t[p].equals("#"))
+ return DEFAULT_NAME;
+ else
+ throw new BAD_PARAM("'" + delimiter + "String' expected '" + t[p]
+ + "' found");
+ }
+
+ StringBuffer bKey = new StringBuffer();
+ p++;
+
+ while (p < t.length && !t[p].equals("#"))
+ bKey.append(t[p++]);
+
+ if (bKey.length() == 0)
+ return DEFAULT_NAME;
+
+ try
+ {
+ return URLDecoder.decode(bKey.toString(), "UTF-8");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new Unexpected("URLDecoder does not support UTF-8", e);
+ }
+ }
+}
diff --git a/gnu/javax/naming/giop/GiopNamingEnumeration.java b/gnu/javax/naming/giop/GiopNamingEnumeration.java
new file mode 100644
index 000000000..9b93f8bb6
--- /dev/null
+++ b/gnu/javax/naming/giop/GiopNamingEnumeration.java
@@ -0,0 +1,187 @@
+/* GiopNamingEnumeration.java -- handles corbaname: urls
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.naming.giop;
+
+import java.util.NoSuchElementException;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+
+import org.omg.CosNaming.Binding;
+import org.omg.CosNaming.BindingIterator;
+import org.omg.CosNaming.BindingIteratorHolder;
+import org.omg.CosNaming.BindingListHolder;
+
+/**
+ * Iterates over name class pairs, obtaining values first from the binding list
+ * and then from the binding iterator.
+ *
+ * @author Audrius Meskauskas
+ */
+public abstract class GiopNamingEnumeration implements NamingEnumeration
+{
+ /**
+ * The array of bindings, returned at once.
+ */
+ Binding[] list;
+
+ /**
+ * The binding iterator to obtain the subsequent bindings. May be null,
+ * if all values are stored in the <code>list</code>.
+ */
+ BindingIterator iterator;
+
+ /**
+ * The batch size.
+ */
+ int batch;
+
+ /**
+ * The position of the element in the binding list, that must be returned
+ * during the subsequent call of the next(). If this field is grater or equal
+ * to the lenght of the list, the subsequent values must be requested from the
+ * iterator.
+ */
+ int p;
+
+ GiopNamingEnumeration(BindingListHolder bh, BindingIteratorHolder bih, int batchSize)
+ {
+ list = bh.value;
+ iterator = bih.value;
+ batch = batchSize;
+ }
+
+ /**
+ * Convert from the CORBA binding into that this enumeration should return.
+ *
+ * @param binding
+ * the binding to convert
+ * @return the value, that must be returned by the {@link #next()}.
+ */
+ public abstract Object convert(Binding binding);
+
+ public void close() throws NamingException
+ {
+ if (iterator != null)
+ {
+ iterator.destroy();
+ iterator = null;
+ }
+ }
+
+ /**
+ * Checks if there are more elements to return.
+ *
+ * @throws NamingException
+ * never
+ */
+ public boolean hasMore() throws NamingException
+ {
+ return hasMoreElements();
+ }
+
+ /**
+ * Returns the next element.
+ *
+ * @throws NamingException
+ * never
+ */
+ public Object next() throws NamingException
+ {
+ return nextElement();
+ }
+
+ /**
+ * Checks if there are more elements to return.
+ */
+ public boolean hasMoreElements()
+ {
+ if (p < 0)
+ return false;
+ else if (p < list.length)
+ return true;
+ else
+ return getMore();
+ }
+
+ /**
+ * Returns the next element.
+ */
+ public Object nextElement()
+ {
+ if (p < 0)
+ throw new NoSuchElementException();
+ else if (p < list.length)
+ return convert(list[p++]);
+ else if (getMore())
+ // getMore updates p
+ return convert(list[p++]);
+ else
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * Tries to obtain more elements, return true on success. Updates the fields
+ * accordingly.
+ */
+ boolean getMore()
+ {
+ if (iterator != null)
+ {
+ BindingListHolder holder = new BindingListHolder();
+ boolean rt = iterator.next_n(batch, holder);
+ if (rt)
+ {
+ // The new pack of the bindings arrived.
+ p = 0;
+ list = holder.value;
+ return true;
+ }
+ else
+ {
+ iterator.destroy();
+ iterator = null;
+ p = -1;
+ return false;
+ }
+ }
+ else
+ return false;
+ }
+}
diff --git a/gnu/javax/naming/giop/GiopNamingServiceFactory.java b/gnu/javax/naming/giop/GiopNamingServiceFactory.java
new file mode 100644
index 000000000..84aa32413
--- /dev/null
+++ b/gnu/javax/naming/giop/GiopNamingServiceFactory.java
@@ -0,0 +1,177 @@
+/* GiopNamingServiceFactory.java -- handles corbaname: urls
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.naming.giop;
+
+import gnu.CORBA.OrbFunctional;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TreeMap;
+
+import javax.naming.Context;
+import javax.naming.Name;
+
+import org.omg.CORBA.ORB;
+
+/**
+ * The context factory to represent the corbaname: style urls. Such URL states
+ * that the CORBA naming service exists on the given host. This service can
+ * return the required object, finding it by the given name. The names are
+ * parsed using the specification of the corbaname urls. Being the naming
+ * service, the returned context supports creating the subcontexts, forwarding
+ * this task to the existing naming service.
+ *
+ * @author Audrius Meskauskas (audriusa@Bioinformatics.org)
+ */
+public class GiopNamingServiceFactory
+{
+ /**
+ * The default naming service provider. It is assumed, that the naming service
+ * is running on the port 900 of the local host, using the GIOP version 1.2
+ */
+ public static final String DEFAULT_PROVIDER =
+ "corbaloc:iiop:1.2@127.0.0.1:900/NameService";
+
+ /**
+ * The table of all instantiated ORB's that are found by they ORB
+ * properties signatures. If all ORB related properties are the same,
+ * the ORB's are shared.
+ */
+ public static Hashtable orbs = new Hashtable();
+
+
+ /**
+ * Create a new instance of the corbaname URL context.
+ */
+ public Object getObjectInstance(Object refObj, Name name, Context nameCtx,
+ Hashtable environment)
+ {
+ String provider = (String) environment.get(Context.PROVIDER_URL);
+ if (provider == null)
+ provider = DEFAULT_PROVIDER;
+
+ String orbSignature = getOrbSignature(environment);
+
+ ORB orb;
+ synchronized (orbs)
+ {
+ orb = (ORB) orbs.get(orbSignature);
+ if (orb == null)
+ {
+ Properties props = new Properties();
+ props.putAll(environment);
+ orb = ORB.init(new String[0], props);
+ orbs.put(orbSignature, orb);
+ final ORB runIt = orb;
+ new Thread()
+ {
+ public void run()
+ {
+ runIt.run();
+ }
+ }.start();
+ }
+ }
+
+ return new GiopNamingServiceURLContext(environment, this, orb);
+ }
+
+ /**
+ * Check if this ORB is still in use (maybe it is time to shutdown it). This
+ * method only works when the Classpath CORBA implementation is used
+ * (otherwise it return without action). The method is called from the close()
+ * method of the created context.
+ *
+ * @param orb
+ * the ORB that maybe is no longer referenced.
+ */
+ public void checkIfReferenced(ORB orb)
+ {
+ synchronized (orbs)
+ {
+ // We can only do this with the Classpath implementation.
+ if (orb instanceof OrbFunctional)
+ {
+ OrbFunctional cOrb = (OrbFunctional) orb;
+ // If there are no connected objects, we can destroy the orb.
+ if (cOrb.countConnectedObjects() == 0)
+ {
+ cOrb.shutdown(false);
+ cOrb.destroy();
+
+ Enumeration keys = orbs.keys();
+ Object key;
+ Remove: while (keys.hasMoreElements())
+ {
+ key = keys.nextElement();
+ if (orbs.get(key) == orb)
+ {
+ orbs.remove(key);
+ break Remove;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Get all properties.
+ */
+ public String getOrbSignature(Map props)
+ {
+ TreeMap map = new TreeMap();
+ map.putAll(props);
+ StringBuffer b = new StringBuffer(50*props.size());
+
+ Iterator iter = map.entrySet().iterator();
+ Map.Entry m;
+ while (iter.hasNext())
+ {
+ m = (Map.Entry) iter.next();
+ b.append(m.getKey());
+ b.append('=');
+ b.append(m.getValue());
+ }
+ return b.toString();
+ }
+}
diff --git a/gnu/javax/naming/giop/GiopNamingServiceURLContext.java b/gnu/javax/naming/giop/GiopNamingServiceURLContext.java
new file mode 100644
index 000000000..50446ac7e
--- /dev/null
+++ b/gnu/javax/naming/giop/GiopNamingServiceURLContext.java
@@ -0,0 +1,840 @@
+/* GiopNamingServiceURLContext.java -- handles corbaname: urls
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.naming.giop;
+
+import gnu.CORBA.NamingService.Ext;
+import gnu.CORBA.NamingService.NameTransformer;
+
+import java.util.Hashtable;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.ContextNotEmptyException;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NameClassPair;
+import javax.naming.NameNotFoundException;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.OperationNotSupportedException;
+import javax.naming.directory.InvalidAttributesException;
+
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.portable.Delegate;
+import org.omg.CORBA.portable.ObjectImpl;
+import org.omg.CosNaming.BindingIteratorHolder;
+import org.omg.CosNaming.BindingListHolder;
+import org.omg.CosNaming.NameComponent;
+import org.omg.CosNaming.NamingContext;
+import org.omg.CosNaming.NamingContextExt;
+import org.omg.CosNaming.NamingContextExtHelper;
+import org.omg.CosNaming.NamingContextHelper;
+import org.omg.CosNaming._NamingContextExtStub;
+import org.omg.CosNaming._NamingContextStub;
+import org.omg.CosNaming.NamingContextPackage.AlreadyBound;
+import org.omg.CosNaming.NamingContextPackage.CannotProceed;
+import org.omg.CosNaming.NamingContextPackage.InvalidName;
+import org.omg.CosNaming.NamingContextPackage.NotFound;
+
+/**
+ * The context to represent the corba naming service. Being the naming service,
+ * the returned context supports creating the subcontexts, forwarding this task
+ * to the existing naming service. When listing bindings, it uses the
+ * {@link Context#BATCHSIZE} property to determine, how many bindings should
+ * be returned at once (the process is transparend)
+ *
+ * @author Audrius Meskauskas (audriusa@Bioinformatics.org)
+ */
+public class GiopNamingServiceURLContext extends CorbalocParser implements
+ Context
+{
+ /**
+ * This number of bindings will be requested from the naming server at once,
+ * while the subsequent bindings will be requested via binding iterator one by
+ * one. Use {@link Context#BATCHSIZE} to override the value of this constant.
+ */
+ public int DEFAULT_BATCH_SIZE = 20;
+
+ /**
+ * The object request broker, used to access the naming service. This field
+ * is only initialised when the context is constructed from the URL.
+ */
+ ORB orb;
+
+ /**
+ * The properties.
+ */
+ Hashtable properties;
+
+ /**
+ * The parent factory.
+ */
+ GiopNamingServiceFactory factory;
+
+ /**
+ * The name transformer to obtain the name from its string representation. The
+ * to_name method of the naming service is avoided as it may be remote and
+ * hence expensive. The conversion rules are standard and cannot be service
+ * specific.
+ */
+ static NameTransformer transformer = new NameTransformer();
+
+ /**
+ * The batch size for list operations - how many to return at once.
+ */
+ public final int howMany;
+
+ /**
+ * Creates a new naming context that uses naming service, represented by the
+ * given CORBA object.
+ *
+ * @param props
+ * the environment table.
+ * @param aFactory
+ * parent factory. This reference is used during cleanup.
+ * @param anOrb
+ * the associated ORB. This reference is used during cleanup.
+ */
+ public GiopNamingServiceURLContext(Hashtable props,
+ GiopNamingServiceFactory aFactory,
+ ORB anOrb)
+ {
+ factory = aFactory;
+ orb = anOrb;
+
+ properties = props;
+ howMany = getBatchSize();
+ }
+
+ public NamingContextExt getService(String address)
+ {
+ org.omg.CORBA.Object nsObject = orb.string_to_object(address);
+ Delegate delegate = ((ObjectImpl) nsObject)._get_delegate();
+
+ // If the IOR provides the IDL ID, we can check if our name
+ // service is old NamingContext or new NamingContextExt.
+ // Not all forms of the URL always provide the IDL id.
+ if (!nsObject._is_a(NamingContextExtHelper.id())
+ && nsObject._is_a(NamingContextHelper.id()))
+ {
+ // We are surely working with the old version.
+ _NamingContextStub stub = new _NamingContextStub();
+ stub._set_delegate(delegate);
+ // The Ext object will add the necessary extensions.
+ return new Ext(stub);
+ }
+ else
+ {
+ // We expecte the service to be the NamingContextExt (this is true
+ // for both Sun's and our implementations). There is no easy way
+ // to check the version.
+ _NamingContextExtStub stub = new _NamingContextExtStub();
+ stub._set_delegate(delegate);
+ return stub;
+ }
+ }
+
+ /**
+ * Split the corbaname name into the address of the naming service (first
+ * part) and the name of the object in the naming service (second part)
+ */
+ public String[] split(String corbaloc) throws InvalidNameException
+ {
+ if (corbaloc.endsWith("#"))
+ corbaloc = corbaloc.substring(0, corbaloc.length() - 1);
+
+ // No name part - parse as corbaname.
+ if (corbaloc.indexOf('#') < 0)
+ {
+ if (!corbaloc.regionMatches(true, 0, pxCORBANAME, 0,
+ pxCORBANAME.length()))
+ throw new InvalidNameException(corbaloc + " must start with "
+ + pxCORBANAME);
+ corbaloc = pxCORBALOC + corbaloc.substring(pxCORBANAME.length());
+ return new String[] { corbaloc, "" };
+ }
+
+ return corbaloc(corbaloc, orb);
+ }
+
+ /**
+ * Give the specified name for the specified object. The passed name must not
+ * be already bound to some other object. The components of the name are
+ * mapped into the components of the CORBA name.
+ *
+ * @param name
+ * the name that will be given to the object (in the scope of this
+ * context).
+ * @param obj
+ * the object being named.
+ * @throws NameAlreadyBoundException
+ * if this name is already used to name some object.
+ * @throws InvalidAttributesException
+ * if the object does not supply all required attributes.
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void bind(Name name, Object obj) throws NamingException
+ {
+ bind(name.toString(), obj);
+ }
+
+ /**
+ * Give the specified name for the specified object. The passed name must not
+ * be already bound to some other object.
+ *
+ * @param name
+ * the name that will be given to the object (in the scope of this
+ * context).
+ * @param obj
+ * the object being named.
+ * @throws NameAlreadyBoundException
+ * if this name is already used to name some object.
+ * @throws InvalidAttributesException
+ * if the object does not supply all required attributes.
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void bind(String name, Object obj) throws NamingException
+ {
+ try
+ {
+ String[] n = split(name);
+ org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
+ getService(n[0]).bind(transformer.toName(n[1]), object);
+ }
+ catch (ClassCastException e)
+ {
+ throw new NamingException(org.omg.CORBA.Object.class + " required ");
+ }
+ catch (InvalidName e)
+ {
+ throw new InvalidNameException();
+ }
+ catch (AlreadyBound e)
+ {
+ throw new NameAlreadyBoundException();
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ /**
+ * Releases all resources, associated with this context. The close() method
+ * can be called several times, but after it has been once invoked, it is not
+ * allowed to call any other method of this context. This method destroys
+ * the ORB, if we have one.
+ *
+ * @throws NamingException
+ */
+ public void close() throws NamingException
+ {
+ if (orb != null && factory != null)
+ {
+ factory.checkIfReferenced(orb);
+ }
+ }
+
+ /**
+ * Not supported.
+ */
+ public Name composeName(Name name, Name prefix) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Not supported
+ */
+ public String composeName(String name1, String name2) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Creates the new naming subcontext and binds it to the current (this)
+ * context. The returned object will wrap around the newly created CORBA
+ * subcontext
+ *
+ * @param subContext
+ * the name of the new context being created
+ * @return the newly created context, bound to the instance of the context on
+ * that the method has been called
+ * @throws NameAlreadyBoundException
+ * if this name is already bound
+ * @throws InvalidAttributesException
+ * if the creation of the new context requires the missing mandatory
+ * attributes
+ * @throws NamingException
+ */
+ public Context createSubcontext(Name subContext) throws NamingException
+ {
+ return createSubcontext(subContext.toString());
+ }
+
+ /**
+ * Creates the new naming subcontext and binds it to the current (this)
+ * context. The returned object will wrap around the newly created CORBA
+ * subcontext
+ *
+ * @param subContext
+ * the name of the new context being created
+ * @return the newly created context, bound to the instance of the context on
+ * that the method has been called
+ * @throws NameAlreadyBoundException
+ * if this name is already bound
+ * @throws InvalidAttributesException
+ * if the creation of the new context requires the missing mandatory
+ * attributes
+ * @throws NamingException
+ */
+ public Context createSubcontext(String subContext) throws NamingException
+ {
+ try
+ {
+ String[] n = split(subContext);
+ org.omg.CORBA.Object subcontext = getService(n[0]).bind_new_context(
+ transformer.toName(n[1]));
+ Hashtable clonedProps = new Hashtable();
+ clonedProps.putAll(properties);
+
+ // Nulls are passed both for orb and factory, as the child contexts
+ // need not to do any cleanup.
+ return new ContextContinuation(subcontext, clonedProps, null, null);
+ }
+ catch (AlreadyBound e)
+ {
+ throw new NameAlreadyBoundException(subContext);
+ }
+ catch (InvalidName e)
+ {
+ throw new InvalidNameException(subContext);
+ }
+ catch (Exception ex)
+ {
+ throw new NamingException(ex.toString());
+ }
+ }
+
+ /**
+ * Removes the naming subcontext from this naming context. Returns without
+ * action if such subcontext does not exist. The context being destroyed must
+ * be empty.
+ *
+ * @param subContext
+ * the name of the subcontext beig removed.
+ * @throws ContextNotEmptyException
+ * if the named context is not empty.
+ * @throws NamingException
+ */
+ public void destroySubcontext(Name subContext) throws NamingException
+ {
+ unbind(subContext);
+ }
+
+ /**
+ * Removes the naming subcontext from this naming context. Returns without
+ * action if such subcontext does not exist. The context being destroyed must
+ * be empty.
+ *
+ * @param subContext
+ * the name of the subcontext beig removed.
+ * @throws ContextNotEmptyException
+ * if the named context is not empty.
+ * @throws NamingException
+ */
+ public void destroySubcontext(String subContext) throws NamingException
+ {
+ unbind(subContext);
+ }
+
+ /**
+ * Returs the empty string.
+ */
+ public String getNameInNamespace() throws NamingException
+ {
+ return "";
+ }
+
+ /**
+ * Not supported.
+ */
+ public NameParser getNameParser(Name name) throws NamingException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Not supported.
+ */
+ public NameParser getNameParser(String name) throws NamingException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Creates and returns the enumeration over the name bindings that are present
+ * the given subcontext. The enumeration elements have the type of
+ * {@link NameClassPair}, providing also information about the class of the
+ * bound object. The behaviour in the case if the bindings are added or
+ * removed later is not defined. The contents of the subcontexts are not
+ * included.
+ *
+ * @param name
+ * the name of the subcontext
+ * @return the enumeration over the names, known for the given subcontext.
+ * @throws NamingException
+ */
+ public NamingEnumeration list(Name name) throws NamingException
+ {
+ return list(name.toString());
+ }
+
+ /**
+ * Creates and returns the enumeration over the name bindings that are present
+ * the given subcontext. The enumeration elements have the type of
+ * {@link NameClassPair}, providing also information about the class of the
+ * bound object. The behaviour in the case if the bindings are added or
+ * removed later is not defined. The contents of the subcontexts are not
+ * included.
+ *
+ * @param name
+ * the name of the subcontext
+ * @return the enumeration over the names, known for the given subcontext.
+ * @throws NamingException
+ */
+ public NamingEnumeration list(String name) throws NamingException
+ {
+ BindingIteratorHolder bi = new BindingIteratorHolder();
+ BindingListHolder bl = new BindingListHolder();
+
+ NamingContext subcontext;
+
+ String [] n = split(name);
+ NamingContextExt service = getService(n[0]);
+
+ if (n[1].length() == 0)
+ subcontext = service;
+ else
+ {
+ try
+ {
+ subcontext = (NamingContextHelper.narrow(service.resolve_str(n[1])));
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+
+ }
+
+ subcontext.list(howMany, bl, bi);
+
+ return new ListEnumeration(bl, bi, howMany);
+ }
+
+ /**
+ * Creates and returns the enumeration over the name - object bindings that
+ * are present the given subcontext. The enumeration elements have the type of
+ * {@link Binding}, providing also information about the class of the bound
+ * object. The behaviour in the case if the bindings are added or removed
+ * later is not defined. The contents of the subcontexts are not included.
+ *
+ * @param name
+ * the name of the subcontext
+ * @return the enumeration over the names, known for the given subcontext.
+ * @throws NamingException
+ */
+ public NamingEnumeration listBindings(Name name) throws NamingException
+ {
+ return listBindings(name.toString());
+ }
+
+ /**
+ * Creates and returns the enumeration over the name - object bindings that
+ * are present the given subcontext. The enumeration elements have the type of
+ * {@link Binding}, providing also information about the class of the bound
+ * object. The behaviour in the case if the bindings are added or removed
+ * later is not defined. The contents of the subcontexts are not included.
+ *
+ * @param name
+ * the name of the subcontext
+ * @return the enumeration over the names, known for the given subcontext.
+ * @throws NamingException
+ */
+ public NamingEnumeration listBindings(String name) throws NamingException
+ {
+ BindingIteratorHolder bi = new BindingIteratorHolder();
+ BindingListHolder bl = new BindingListHolder();
+
+ NamingContext subcontext;
+
+ String [] n = split(name);
+ NamingContextExt service = getService(n[0]);
+
+ if (n[1].length() == 0)
+ subcontext = service;
+ else
+ {
+ try
+ {
+ subcontext = (NamingContextHelper.narrow(service.resolve_str(n[1])));
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+
+ }
+
+ subcontext.list(howMany, bl, bi);
+
+ return new ListBindingsEnumeration(bl, bi, howMany, subcontext);
+ }
+
+ /**
+ * Gets the previously named object by name. If the passed name is empty, the
+ * method should return a cloned instance of this naming context.
+ *
+ * @param name
+ * the name of the object being searched in this context
+ * @return the named object
+ * @throws NameNotFoundException
+ * if the name is not found
+ */
+ public Object lookup(Name name) throws NamingException
+ {
+ return lookup(name.toString());
+ }
+
+ /**
+ * Gets the previously named object by name. If the passed name is empty, the
+ * method should return a cloned instance of this naming context.
+ *
+ * @param name
+ * the name of the object being searched in this context
+ * @return the named object
+ * @throws NamingException
+ * if the naming fails.
+ */
+ public Object lookup(String name) throws NamingException
+ {
+ try
+ {
+ String [] n = split(name);
+ NamingContextExt service = getService(n[0]);
+ return service.resolve_str(n[1]);
+ }
+ catch (NotFound e)
+ {
+ throw new NameNotFoundException();
+ }
+ catch (InvalidName e)
+ {
+ throw new InvalidNameException();
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ /**
+ * Not supported.
+ */
+ public Object lookupLink(Name name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Not supported.
+ */
+ public Object lookupLink(String name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Give the specified name for the specified object. Unlike bind, this method
+ * silently replaces the existing binding for this name, if one exists.
+ *
+ * @param name
+ * the name that will be given to the object (in the scope of this
+ * context).
+ * @param obj
+ * the object being named.
+ * @throws InvalidAttributesException
+ * if the object does not supply all required attributes.
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void rebind(Name name, Object obj) throws NamingException
+ {
+ rebind(name.toString(), obj);
+ }
+
+ /**
+ * Give the specified name for the specified object. Unlike bind, this method
+ * silently replaces the existing binding for this name, if one exists.
+ *
+ * @param name
+ * the name that will be given to the object (in the scope of this
+ * context).
+ * @param obj
+ * the object being named.
+ * @throws InvalidAttributesException
+ * if the object does not supply all required attributes.
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void rebind(String name, Object obj) throws NamingException
+ {
+ try
+ {
+ String[] n = split(name);
+ NamingContextExt service = getService(n[0]);
+
+ org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
+ service.rebind(transformer.toName(n[1]), object);
+ }
+ catch (ClassCastException e)
+ {
+ throw new NamingException(org.omg.CORBA.Object.class + " required ");
+ }
+ catch (InvalidName e)
+ {
+ throw new InvalidNameException();
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ /**
+ * Renames the existing binding, removing the existing and giving the new name
+ * for the same object.
+ *
+ * @param oldName
+ * the existing name of the known object
+ * @param newName
+ * the new name of the same object
+ * @throws NameNotFoundException
+ * if the oldName is unknown for this context
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void rename(Name oldName, Name newName) throws NamingException
+ {
+ Object object = lookup(oldName);
+ unbind(oldName);
+ bind(newName, object);
+ }
+
+ /**
+ * Renames the existing binding, removing the existing and giving the new name
+ * for the same object.
+ *
+ * @param oldName
+ * the existing name of the known object
+ * @param newName
+ * the new name of the same object
+ * @throws NameNotFoundException
+ * if the oldName is unknown for this context
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void rename(String oldName, String newName) throws NamingException
+ {
+ Object object = lookup(oldName);
+ unbind(oldName);
+ bind(newName, object);
+ }
+
+ /**
+ * Removes the name - object mapping from the current context. This method
+ * returns without action if the name is not bound to an object in the
+ * terminal context, but throws {@link NameNotFoundException} if one of the
+ * intermadiate contexts does not exist.
+ *
+ * @param name
+ * the name to be removed
+ * @throws NameNotFoundException
+ * if one of the intermediate naming contexts does not exist. Will
+ * not be thrown if just the terminal binding is missing.
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void unbind(Name name) throws NamingException
+ {
+ unbind(name.toString());
+ }
+
+ /**
+ * Removes the name - object mapping from the current context. This method
+ * returns without action if the name is not bound to an object in the
+ * terminal context, but throws {@link NameNotFoundException} if one of the
+ * intermadiate contexts does not exist.
+ *
+ * @param name
+ * the name to be removed
+ * @throws NameNotFoundException
+ * if one of the intermediate naming contexts does not exist. Will
+ * not be thrown if just the terminal binding is missing.
+ * @throws NamingException
+ * if the naming operation has failed due other reasons.
+ */
+ public void unbind(String name) throws NamingException
+ {
+ try
+ {
+ String[] n = split(name);
+ NamingContextExt service = getService(n[0]);
+
+ service.unbind(transformer.toName(n[1]));
+ }
+ catch (NotFound e)
+ {
+ throw new NameNotFoundException(name);
+ }
+ catch (CannotProceed e)
+ {
+ throw new ContextNotEmptyException(name);
+ }
+ catch (InvalidName e)
+ {
+ throw new InvalidNameException(name);
+ }
+ }
+
+ /**
+ * Add new environment property to the environment of this context. Both name
+ * and value of the new property must not be null. If the property is already
+ * defined, is current value is replaced by the propVal.
+ *
+ * @param key
+ * the name of the new property
+ * @param value
+ * the value of the new property
+ * @return the previous value of this property or null if the property has not
+ * been previously defined
+ * @throws NamingException
+ */
+ public Object addToEnvironment(String key, Object value)
+ throws NamingException
+ {
+ if (key == null || value == null)
+ throw new NullPointerException();
+ return properties.put(key, value);
+ }
+
+ /**
+ * Returns the environment, associated with this naming context. The returned
+ * table should never be modified by the caller. Use {@link #addToEnvironment}
+ * and {@link #removeFromEnvironment} to modify the environement, if needed.
+ *
+ * @return the table, representing the environment of this context
+ * @throws NamingException
+ */
+ public Hashtable getEnvironment() throws NamingException
+ {
+ return properties;
+ }
+
+ /**
+ * Removes the property with the given name from the environment. Returns
+ * without action if this property is not defined.
+ *
+ * @param propName
+ * the name of the property being removed.
+ * @return the value of the property that has been removed or null if the
+ * property was not defined.
+ * @throws NamingException
+ */
+ public Object removeFromEnvironment(String propName) throws NamingException
+ {
+ return properties.remove(propName);
+ }
+
+ /**
+ * Convert the {@link Name} into array of the name components, required to the
+ * CORBA naming service. First the string representation is obtained, then
+ * it is converted using parsing rules of the CORBA name.
+ *
+ * @param name
+ * then name to convert
+ * @return the converted array of components.
+ */
+ public NameComponent[] toGiop(Name name) throws InvalidName
+ {
+ return transformer.toName(name.toString());
+ }
+
+ /**
+ * Get the batch size from the environment properties. The batch size is used
+ * for listing operations.
+ *
+ * @return the batch size, or some default value if not specified.
+ */
+ public int getBatchSize()
+ {
+ int batchSize = DEFAULT_BATCH_SIZE;
+ Object bs = properties.get(Context.BATCHSIZE);
+ if (bs != null)
+ {
+ try
+ {
+ int b = Integer.parseInt(bs.toString());
+ if (b >= 0)
+ batchSize = b;
+ }
+ catch (NumberFormatException e)
+ {
+ // OK, use default value.
+ }
+ }
+ return batchSize;
+ }
+
+}
diff --git a/gnu/javax/naming/giop/ListBindingsEnumeration.java b/gnu/javax/naming/giop/ListBindingsEnumeration.java
new file mode 100644
index 000000000..00f4a0779
--- /dev/null
+++ b/gnu/javax/naming/giop/ListBindingsEnumeration.java
@@ -0,0 +1,116 @@
+/* ListBindingsEnumeration.java -- handles corbaname: urls
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.naming.giop;
+
+import javax.naming.NamingEnumeration;
+
+import org.omg.CosNaming.Binding;
+import org.omg.CosNaming.BindingIteratorHolder;
+import org.omg.CosNaming.BindingListHolder;
+import org.omg.CosNaming.NamingContext;
+
+/**
+ * Iterates over bindings, obtaining values first from the binding list and then
+ * from the binding iterator.
+ *
+ * @author Audrius Meskauskas
+ */
+public class ListBindingsEnumeration extends GiopNamingEnumeration implements
+ NamingEnumeration
+{
+ /**
+ * The naming service, to resolve the objects.
+ */
+ NamingContext service;
+
+ /**
+ * Create the new enumeration
+ *
+ * @param bh
+ * holder, containing the first portion of the bindings
+ * @param bih
+ * the iterator, containing the remaining bindings
+ * @param batchSize
+ * the number of bindings the the iterator will be requested to
+ * return as a single pack
+ * @param aService
+ * the naming service, used to obtain the objects, bound to the
+ * names.
+ */
+ public ListBindingsEnumeration(BindingListHolder bh,
+ BindingIteratorHolder bih, int batchSize,
+ NamingContext aService)
+ {
+ super(bh, bih, batchSize);
+ service = aService;
+ }
+
+ /**
+ * Convert from the CORBA binding into the javax.naming binding. As the CORBA
+ * naming service binding does not contain the object itself, this method
+ * makes the additional calls to the naming service.
+ *
+ * @param binding
+ * the binding to convert
+ * @return the value, that must be returned by the {@link #next()}.
+ */
+ public Object convert(Binding binding)
+ {
+ StringBuffer name = new StringBuffer();
+
+ for (int i = 0; i < binding.binding_name.length; i++)
+ {
+ name.append(binding.binding_name[i]);
+ if (i < binding.binding_name.length - 1)
+ name.append('/');
+ }
+
+ try
+ {
+ Object object = service.resolve(binding.binding_name);
+ return new javax.naming.Binding(name.toString(), object);
+ }
+ catch (Exception e)
+ {
+ // Probably was removed by the concurent thread.
+ return null;
+ }
+ }
+
+}
diff --git a/gnu/javax/naming/giop/ListEnumeration.java b/gnu/javax/naming/giop/ListEnumeration.java
new file mode 100644
index 000000000..2e64e67d3
--- /dev/null
+++ b/gnu/javax/naming/giop/ListEnumeration.java
@@ -0,0 +1,116 @@
+/* ListEnumeration.java -- handles corbaname: urls
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.naming.giop;
+
+import javax.naming.NameClassPair;
+import javax.naming.NamingEnumeration;
+
+import org.omg.CosNaming.Binding;
+import org.omg.CosNaming.BindingIteratorHolder;
+import org.omg.CosNaming.BindingListHolder;
+import org.omg.CosNaming.BindingType;
+import org.omg.CosNaming.NamingContext;
+
+/**
+ * Iterates over name class pairs, obtaining values first from the binding list
+ * and then from the binding iterator.
+ *
+ * @author Audrius Meskauskas
+ */
+public class ListEnumeration extends GiopNamingEnumeration implements
+ NamingEnumeration
+{
+ /**
+ * Create the new enumeration
+ *
+ * @param bh
+ * holder, containing the first portion of the bindings
+ * @param bih
+ * the iterator, containing the remaining bindings
+ * @param batchSize
+ * the number of bindings the the iterator will be requested to
+ * return as a single pack
+ */
+ public ListEnumeration(BindingListHolder bh,
+ BindingIteratorHolder bih, int batchSize)
+ {
+ super(bh, bih, batchSize);
+ }
+
+ /**
+ * Convert from the CORBA binding into the {@link NameClassPair} that this
+ * enumeration should return. This method converts into NameClassPair,
+ * connecting the name components with slashes and setting the class name
+ * to either NamingContext or GIOP Object.
+ *
+ * @param binding
+ * the binding to convert
+ * @return the value, that must be returned by the {@link #next()}.
+ */
+ public Object convert(Binding binding)
+ {
+ StringBuffer name = new StringBuffer();
+
+ for (int i = 0; i < binding.binding_name.length; i++)
+ {
+ name.append(binding.binding_name[i]);
+ if (i < binding.binding_name.length - 1)
+ name.append('/');
+ }
+
+ String className;
+
+ switch (binding.binding_type.value())
+ {
+ case BindingType._ncontext:
+ className = NamingContext.class.getName();
+ break;
+ case BindingType._nobject:
+ className = org.omg.CORBA.Object.class.getName();
+ break;
+ default:
+ className = Object.class.getName();
+ break;
+ }
+
+ NameClassPair pair = new NameClassPair(name.toString(), className);
+ return pair;
+ }
+
+}
diff --git a/gnu/javax/naming/ictxImpl/trans/GnuName.java b/gnu/javax/naming/ictxImpl/trans/GnuName.java
new file mode 100644
index 000000000..b20bfa4ea
--- /dev/null
+++ b/gnu/javax/naming/ictxImpl/trans/GnuName.java
@@ -0,0 +1,467 @@
+/* GnuName.java -- implementation of the javax.naming.Name
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.naming.ictxImpl.trans;
+
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+
+/**
+ * The implementation of the {@link Name}.
+ *
+ * @author Audrius Meskauskas
+ */
+public class GnuName
+ implements Name
+{
+ /**
+ * The enumeration to traverse over name components.
+ */
+ class GnuNameEnum
+ implements Enumeration
+ {
+ /**
+ * Get the new enumeration that enumerates from the given position forward
+ *
+ * @param position the position of the first name component to enumerate (0
+ * means first element)
+ */
+ GnuNameEnum(int position)
+ {
+ nxt = from + position;
+ }
+
+ /**
+ * The position of the next enumeration component to be returned or -1 if
+ * the end has been reached.
+ */
+ int nxt;
+
+ /**
+ * Check if there are more elements in this enumeration.
+ */
+ public boolean hasMoreElements()
+ {
+ return nxt >= 0;
+ }
+
+ /**
+ * Return the next element or throw a NoSuchElementException if there is no
+ * any.
+ */
+ public Object nextElement()
+ {
+ if (nxt < 0)
+ throw new NoSuchElementException();
+ Object r = content[nxt++];
+
+ if (nxt - from == length)
+ nxt = - 1;
+
+ return r;
+ }
+ }
+
+ private static final long serialVersionUID = - 3617482732056931635L;
+
+ /**
+ * The hashcode
+ */
+ int hash;
+
+ /**
+ * The content buffer of the name. This buffer may be shared, so the array
+ * member content should never be modified.
+ */
+ String[] content;
+
+ /**
+ * The place, inclusive, where the name content starts in the content buffer.
+ */
+ int from;
+
+ /**
+ * The length of the name.
+ */
+ int length;
+
+ /**
+ * Creates the unitialised name.
+ */
+ protected GnuName()
+ {
+
+ }
+
+ /**
+ * Creates the name, containing from the given chain of the atomic components.
+ *
+ * @param name the array, containing the name components.
+ */
+ public GnuName(String[] name)
+ {
+ this(name, 0, name.length);
+ }
+
+ /**
+ * Creates the name that uses the given portion of the array for its
+ * components.
+ */
+ public GnuName(String[] buffer, int useFrom, int useLength)
+ {
+ content = buffer;
+ from = useFrom;
+ length = useLength;
+ }
+
+ /**
+ * Inserts the given <code>String</code> component to this <code>Name</code>
+ * at the given index. The method modifies the current <code>Name</code> and
+ * then returns it.
+ *
+ * @exception ArrayIndexOutOfBoundsException if the given index is smaller
+ * then zero or greater then or equal to <code>size()</code>.
+ * @exception InvalidNameException if the given <code>String</code> is not a
+ * valid component for this <code>Name</code>.
+ */
+ public Name add(int posn, String comp) throws InvalidNameException
+ {
+ String[] nc = new String[content.length + 1];
+ System.arraycopy(content, from, nc, 0, posn);
+ nc[posn] = comp;
+ System.arraycopy(content, from + posn, nc, posn + 1, length - posn);
+
+ content = nc;
+ from = 0;
+ length = content.length;
+ hash = 0;
+ return this;
+ }
+
+ /**
+ * Adds the given <code>String</code> component to the end of this
+ * <code>Name</code>. The method modifies the current <code>Name</code>
+ * and then returns it.
+ *
+ * @exception InvalidNameException if the given <code>String</code> is not a
+ * valid component for this <code>Name</code>.
+ */
+ public Name add(String comp) throws InvalidNameException
+ {
+ String[] nc = new String[content.length + 1];
+ System.arraycopy(content, from, nc, 0, length);
+ nc[nc.length - 1] = comp;
+
+ content = nc;
+ from = 0;
+ length = content.length;
+ hash = 0;
+ return this;
+ }
+
+ /**
+ * Inserts all the components of the given <code>Name</code> to this
+ * <code>Name</code> at the given index. Components after this index (if
+ * any) are shifted up. The method modifies the current <code>Name</code>
+ * and then returns it.
+ *
+ * @exception ArrayIndexOutOfBoundsException if the given index is smaller
+ * then zero or greater then or equal to <code>size()</code>.
+ * @exception InvalidNameException if any of the given components is not a
+ * valid component for this <code>Name</code>.
+ */
+ public Name addAll(int posn, Name n) throws InvalidNameException
+ {
+ String[] nc = new String[length + n.size()];
+ System.arraycopy(content, from, nc, 0, posn);
+
+ int i = posn;
+ for (int p = 0; p < n.size(); i++, p++)
+ nc[i] = n.get(p);
+
+ System.arraycopy(content, from + posn, nc, i, length - posn);
+
+ length = length + n.size();
+ hash = 0;
+ content = nc;
+ return this;
+ }
+
+ /**
+ * Adds all the components of the given <code>Name</code> to the end of this
+ * <code>Name</code>. The method modifies the current <code>Name</code>
+ * and then returns it.
+ *
+ * @exception InvalidNameException if any of the given components is not a
+ * valid component for this <code>Name</code>.
+ */
+ public Name addAll(Name suffix) throws InvalidNameException
+ {
+ String[] nc = new String[length + suffix.size()];
+ System.arraycopy(content, from, nc, 0, length);
+
+ for (int i = length, p = 0; i < nc.length; i++, p++)
+ nc[i] = suffix.get(p);
+
+ length = length + suffix.size();
+ hash = 0;
+ content = nc;
+ return this;
+ }
+
+ /**
+ * Compares the given object to this <code>Name</code>. Returns a negative
+ * value if the given <code>Object</code> is smaller then this
+ * <code>Name</code>, a positive value if the <code>Object</code> is
+ * bigger, and zero if the are equal. If the <code>Object</code> is not of a
+ * class that can be compared to the class of this <code>Name</code> then a
+ * <code>ClassCastException</code> is thrown. Note that it is not guaranteed
+ * that <code>Name</code>s implemented in different classes can be
+ * compared. The definition of smaller, bigger and equal is up to the actual
+ * implementing class.
+ */
+ public int compareTo(Object obj)
+ {
+ Name n = (Name) obj;
+
+ int l = Math.min(length, n.size());
+ int c;
+
+ for (int i = 0; i < l; i++)
+ {
+ c = content[from + i].compareTo(n.get(i));
+ if (c != 0)
+ return c;
+ }
+ return length - n.size();
+ }
+
+ /**
+ * Returns <code>true</code> if this <code>Name</code> ends with the
+ * components of the given <code>Name</code>, <code>false</code>
+ * otherwise.
+ */
+ public boolean endsWith(Name n)
+ {
+ if (n.size() > length)
+ return false;
+
+ int ofs = length - n.size() + from;
+
+ for (int i = 0; i < n.size(); i++, ofs++)
+ if (! content[ofs].equals(n.get(i)))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Gets the component at the given index.
+ *
+ * @exception ArrayIndexOutOfBoundsException if the given index is smaller
+ * then zero or greater then or equal to <code>size()</code>.
+ */
+ public String get(int posn)
+ {
+ return content[from + posn];
+ }
+
+ /**
+ * Returns a non-null (but possibly empty) <code>Enumeration</code> of the
+ * components of the <code>Name</code> as <code>String</code>s.
+ */
+ public Enumeration getAll()
+ {
+ return new GnuNameEnum(0);
+ }
+
+ /**
+ * Returns the components till the given index as a <code>Name</code>. The
+ * returned <code>Name</code> can be modified without changing the original.
+ *
+ * @param posn the ending position, exclusive
+ * @exception ArrayIndexOutOfBoundsException if the given index is smaller
+ * then zero or greater then or equal to <code>size()</code>.
+ */
+ public Name getPrefix(int posn)
+ {
+ return new GnuName(content, from, posn);
+ }
+
+ /**
+ * Returns the components from the given index till the end as a
+ * <code>Name</code>. The returned <code>Name</code> can be modified
+ * without changing the original.
+ *
+ * @param posn the starting position, inclusive. If it is equal to the size of
+ * the name, the empty name is returned.
+ * @exception ArrayIndexOutOfBoundsException if the given index is smaller
+ * then zero or greater then or equal to <code>size()</code>.
+ */
+ public Name getSuffix(int posn)
+ {
+ return new GnuName(content, from + posn, length - posn);
+ }
+
+ /**
+ * Returns <code>true</code> if the number of components of this
+ * <code>Name</code> is zero, <code>false</code> otherwise.
+ */
+ public boolean isEmpty()
+ {
+ return length == 0;
+ }
+
+ /**
+ * Removes the component at the given index from this <code>Name</code>.
+ * The method modifies the current <code>Name</code> and then returns it.
+ *
+ * @exception InvalidNameException if the name size reduces below zero.
+ */
+ public Object remove(int posn) throws InvalidNameException
+ {
+ if (length == 0)
+ throw new InvalidNameException("negative size");
+ else
+ {
+ length--;
+ if (posn == 0)
+ from++;
+ else if (posn < length)
+ {
+ String[] nc = new String[length];
+ System.arraycopy(content, from, nc, 0, posn);
+ System.arraycopy(content, from + posn + 1, nc, posn, length - posn);
+ content = nc;
+ from = 0;
+ }
+ }
+ hash = 0;
+ return this;
+ }
+
+ /**
+ * Returns the number of components of this <code>Name</code>. The returned
+ * number can be zero.
+ */
+ public int size()
+ {
+ return length;
+ }
+
+ /**
+ * Returns <code>true</code> if this <code>Name</code> starts with the
+ * components of the given <code>Name</code>, <code>false</code>
+ * otherwise.
+ */
+ public boolean startsWith(Name n)
+ {
+ if (n.size() > length)
+ return false;
+
+ for (int i = 0; i < n.size(); i++)
+ if (! content[from + i].equals(n.get(i)))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Returns a clone of this <code>Name</code>. It will be a deep copy of all
+ * the components of the <code>Name</code> so that changes to components of
+ * the components does not change the component in this <code>Name</code>.
+ */
+ public Object clone()
+ {
+ return new GnuName(content, from, length);
+ }
+
+ /**
+ * The name is equal to other name if they contents are equal.
+ */
+ public boolean equals(Object arg0)
+ {
+ if (this == arg0)
+ return true;
+ else if (arg0 instanceof Name)
+ {
+ Name n = (Name) arg0;
+ if (length != n.size())
+ return false;
+
+ for (int i = 0; i < length; i++)
+ if (! content[from + i].equals(n.get(i)))
+ return false;
+ return true;
+ }
+ else
+ return false;
+ }
+
+ /**
+ * Overridden to make consistent with equals.
+ */
+ public int hashCode()
+ {
+ if (hash == 0 && length > 0)
+ {
+ int s = 0;
+ for (int i = from; i < from + length; i++)
+ s ^= content[i].hashCode();
+ hash = s;
+ }
+ return hash;
+ }
+
+ /**
+ * Get the string representation, separating the name components by slashes
+ */
+ public String toString()
+ {
+ StringBuffer b = new StringBuffer();
+ for (int i = 0; i < length; i++)
+ {
+ b.append(get(i));
+ if (i < length - 1)
+ b.append('/');
+ }
+ return b.toString();
+ }
+}
diff --git a/gnu/javax/naming/jndi/url/corbaname/corbanameURLContextFactory.java b/gnu/javax/naming/jndi/url/corbaname/corbanameURLContextFactory.java
new file mode 100644
index 000000000..7fe2e5c8c
--- /dev/null
+++ b/gnu/javax/naming/jndi/url/corbaname/corbanameURLContextFactory.java
@@ -0,0 +1,53 @@
+/* corbanameURLContextFactory.java -- handles corbaname: urls
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.naming.jndi.url.corbaname;
+
+import gnu.javax.naming.giop.GiopNamingServiceFactory;
+
+import javax.naming.spi.ObjectFactory;
+
+/**
+ * The GIOP URL context factory.
+ *
+ * @author Audrius Meskauskas (audriusa@Bioinformatics.org)
+ */
+public class corbanameURLContextFactory extends GiopNamingServiceFactory
+ implements ObjectFactory
+{
+ // Nothing to override here.
+}
diff --git a/gnu/javax/naming/jndi/url/rmi/ContextContinuation.java b/gnu/javax/naming/jndi/url/rmi/ContextContinuation.java
new file mode 100644
index 000000000..de79b93c3
--- /dev/null
+++ b/gnu/javax/naming/jndi/url/rmi/ContextContinuation.java
@@ -0,0 +1,597 @@
+/* ContextContinuation.java -- RMI naming context
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.naming.jndi.url.rmi;
+
+import java.rmi.AccessException;
+import java.rmi.AlreadyBoundException;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.naming.CommunicationException;
+import javax.naming.Context;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NameNotFoundException;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.OperationNotSupportedException;
+
+/**
+ * The implementation of the RMI URL context. This context connects
+ *
+ * @author Audrius Meskauskas
+ */
+public class ContextContinuation implements Context
+{
+ /**
+ * The default registry location.
+ */
+ public static final String DEFAULT_REGISTRY_LOCATION = "rmi://localhost:1099";
+
+ /**
+ * The local or remote RMI registry, performing the actual work for this
+ * context.
+ */
+ Registry registry;
+
+ /**
+ * The properties.
+ */
+ Properties properties;
+
+ /**
+ * The flag, indicating, that the lookup methods were called before.
+ * If the lookup methods were called before, the existing ORB cannot be
+ * destroyed, as references to the existing objects will become
+ * unfunctional.
+ */
+ boolean lookupCalled;
+
+ /**
+ * Add new environment property to the environment of this context. Both name
+ * and value of the new property must not be null. If the property is already
+ * defined, is current value is replaced by the propVal. This method replaces
+ * the registry. The new registry will be lazily instantiated on the first
+ * call.
+ *
+ * @param propName
+ * the name of the new property
+ * @param propVal
+ * the value of the new property
+ * @return the previous value of this property or null if the property has not
+ * been previously defined
+ */
+ public Object addToEnvironment(String key, Object value)
+ {
+ removeRegistry();
+ if (key == null || value == null)
+ throw new NullPointerException();
+ return properties.put(key, value);
+ }
+
+ /**
+ * Returns the environment, associated with this naming context. The returned
+ * table should never be modified by the caller (the registry would not be updated
+ * in such case). Use {@link #addToEnvironment} and
+ * {@link #removeFromEnvironment} to modify the environement, if needed.
+ *
+ * @return the table, representing the environment of this context
+ * @throws NamingException
+ */
+ public Hashtable getEnvironment() throws NamingException
+ {
+ return properties;
+ }
+
+ /**
+ * Removes the property with the given name from the environment. Returns
+ * without action if this property is not defined. Replaces the ORB,
+ * constructing the new ORB with the changes set of properties (you can
+ * replace the CORBA implementation provider, for instance). The new ORB will
+ * be lazily instantiated on the first call.
+ *
+ * @param propName
+ * the name of the property being removed.
+ * @return the value of the property that has been removed or null if the
+ * property was not defined.
+ * @throws NamingException
+ */
+ public Object removeFromEnvironment(String propName) throws NamingException
+ {
+ removeRegistry();
+ return properties.remove(propName);
+ }
+
+ /**
+ * Remove the current registry reference.
+ */
+ public void removeRegistry()
+ {
+ registry = null;
+ }
+
+ /**
+ * Get the cached or new registry reference.
+ *
+ * @return the registry reference, either cached or new.
+ */
+ public Registry getRegistry() throws NamingException
+ {
+ if (registry == null)
+ {
+ String address = properties.getProperty(Context.PROVIDER_URL,
+ DEFAULT_REGISTRY_LOCATION);
+
+ // The format like rmi://localhost:1099 is expected. Parse.
+ if (!address.startsWith("rmi://"))
+ throw new InvalidNameException(address);
+
+ String a = address.substring("rmi://".length());
+
+ // The colon, if present, indicates the start of the port number.
+ int colon = a.lastIndexOf(':');
+ int port;
+
+ try
+ {
+ if (colon >=0)
+ {
+ port = Integer.parseInt(a.substring(colon+1));
+ a = a.substring(0, colon);
+ }
+ else
+ port = Registry.REGISTRY_PORT;
+ }
+ catch (NumberFormatException e1)
+ {
+ throw new InvalidNameException(address);
+ }
+
+ try
+ {
+ registry = LocateRegistry.getRegistry(a, port);
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ }
+ return registry;
+ }
+
+ /**
+ * Create the rmi url context that works, talking with the given RMI registry.
+ *
+ * @param props
+ * the properties for this context
+ * @param initialRegistry
+ * the initial value of the registry
+ */
+ public ContextContinuation(Map props, Registry initialRegistry)
+ {
+ properties = new Properties();
+ if (props != null)
+ properties.putAll(props);
+ registry = initialRegistry;
+ }
+
+ /**
+ * Bind the given name into this context. The .toString() is called to
+ * convert into the string representation, required by RMI registry.
+ *
+ * @throws NamingException if the object is not an instance of Remote
+ */
+ public void bind(Name name, Object obj) throws NamingException
+ {
+ bind(name.toString(), obj);
+ }
+
+ /**
+ * Bind the given name into this context.
+ */
+ public void bind(String name, Object obj) throws NamingException
+ {
+ try
+ {
+ getRegistry().bind(name, (Remote) obj);
+ }
+ catch (AccessException e)
+ {
+ throw new NamingException("access:"+e.toString());
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ catch (AlreadyBoundException e)
+ {
+ throw new NameAlreadyBoundException(name);
+ }
+ catch (ClassCastException c)
+ {
+ throw new NamingException("Only Remote can be bound:"
+ + obj.getClass().getName());
+ }
+ }
+
+ /**
+ * Not supported.
+ */
+ public Name composeName(Name name, Name prefix) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Not supported.
+ */
+ public String composeName(String name, String prefix) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Subcontexts are not supporte by RMI registry. The only supported case is an
+ * empty name (returns the cloned instance of self).
+ */
+ public Context createSubcontext(Name name) throws NamingException
+ {
+ if (name.size() == 0)
+ return new rmiURLContext(properties);
+ else
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Subcontexts are not supporte by RMI registry. The only supported case is an
+ * empty name (returns the cloned instance of self).
+ */
+ public Context createSubcontext(String name) throws NamingException
+ {
+ if (name.length() == 0)
+ return new rmiURLContext(properties);
+ else
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Subcontexts are not supporte by RMI registry.
+ */
+ public void destroySubcontext(Name name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Subcontexts are not supporte by RMI registry.
+ */
+ public void destroySubcontext(String name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Returns the naming service URL, same that was passed vie
+ * {@link Context#PROVIDER_URL}.
+ */
+ public String getNameInNamespace() throws NamingException
+ {
+ return properties.getProperty(Context.PROVIDER_URL,
+ DEFAULT_REGISTRY_LOCATION);
+ }
+
+ /**
+ * Not supported, this context never parses any names.
+ */
+ public NameParser getNameParser(Name name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Not supported, this context never parses any names.
+ */
+ public NameParser getNameParser(String name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * List existing bindings of this context (the parameter must be empty name,
+ * indicating the root context). The class name of the returned name class
+ * pairs is "Remote", as this "quick preview" method should probably not call
+ * the naming service again. Use listBindings if more details are required.
+ */
+ public NamingEnumeration list(Name name) throws NamingException
+ {
+ if (name.size() > 0)
+ throw new OperationNotSupportedException("Only empty name is accepted");
+ return list("");
+ }
+
+ /**
+ * List existing bindings of this context (the parameter must be empty string,
+ * indicating the root context). The class name of the returned name class
+ * pairs is "Remote", as this "quick preview" method should probably not call
+ * the naming service again. Use listBindings if more details are required.
+ */
+ public NamingEnumeration list(String name) throws NamingException
+ {
+ if (name.length() > 0)
+ throw new OperationNotSupportedException("Only empty name is accepted");
+
+ try
+ {
+ return new ListEnumeration(getRegistry().list());
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ /**
+ * List existing bindings of this context (the parameter must be empty name,
+ * indicating the root context).
+ */
+ public NamingEnumeration listBindings(Name name) throws NamingException
+ {
+ if (name.size() > 0)
+ throw new OperationNotSupportedException("Only empty name is accepted");
+ return listBindings("");
+ }
+
+ /**
+ * List existing bindings of this context (the parameter must be empty name,
+ * indicating the root context).
+ */
+ public NamingEnumeration listBindings(String name) throws NamingException
+ {
+ if (name.length() > 0)
+ throw new OperationNotSupportedException("Only empty name is accepted");
+
+ try
+ {
+ Registry r = getRegistry();
+ return new ListBindingsEnumeration(r.list(), r);
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ /**
+ * Not supported.
+ */
+ public Object lookupLink(Name name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Not supported.
+ */
+ public Object lookupLink(String name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Rebinds this object.
+ *
+ * @param name
+ * the object name (.toString()) is used to convert into string
+ * representation.
+ * @param the
+ * object (must be an instance of Remote).
+ */
+ public void rebind(Name name, Object obj) throws NamingException
+ {
+ rebind(name.toString(), obj);
+ }
+
+ /**
+ * Rebinds this object.
+ *
+ * @param name
+ * the object name.
+ * @param the
+ * object (must be an instance of Remote).
+ */
+ public void rebind(String name, Object obj) throws NamingException
+ {
+ try
+ {
+ getRegistry().rebind(name, (Remote) obj);
+ }
+ catch (AccessException e)
+ {
+ throw new NamingException("access:"+e.toString());
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ catch (ClassCastException c)
+ {
+ throw new NamingException("Only Remote can be bound:"
+ + obj.getClass().getName());
+ }
+ }
+
+ /**
+ * Renames the object. If the new name is already bound in the given context,
+ * the {@link AlreadyBoundException} is thrown and the oldName binding is
+ * preserved.
+ */
+ public void rename(Name oldName, Name newName) throws NamingException
+ {
+ rename(oldName.toString(), newName.toString());
+ }
+
+ /**
+ * Renames the object. If the new name is already bound in the given context,
+ * the {@link AlreadyBoundException} is thrown and the oldName binding is
+ * preserved.
+ */
+ public synchronized void rename(String oldName, String newName)
+ throws NamingException
+ {
+ try
+ {
+ Registry r = getRegistry();
+ Remote object = r.lookup(oldName);
+ r.unbind(oldName);
+ try
+ {
+ r.bind(newName, object);
+ }
+ catch (AlreadyBoundException e)
+ {
+ // Bind it back.
+ try
+ {
+ r.bind(oldName, object);
+ }
+ catch (AlreadyBoundException e1)
+ {
+ // We have just removed this name.
+ throw new InternalError();
+ }
+ throw new NameAlreadyBoundException(newName);
+ }
+ }
+ catch (AccessException e)
+ {
+ throw new NamingException(e.toString());
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ catch (NotBoundException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ }
+
+ /**
+ * Unbind the object.
+ */
+ public void unbind(Name name) throws NamingException
+ {
+ unbind(name.toString());
+ }
+
+ /**
+ * Unbind the object.
+ */
+ public void unbind(String name) throws NamingException
+ {
+ try
+ {
+ getRegistry().unbind(name);
+ }
+ catch (AccessException e)
+ {
+ throw new NamingException(e.toString());
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ catch (NotBoundException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ }
+
+ /**
+ * Release the associated resources.
+ */
+ public void close() throws NamingException
+ {
+ removeRegistry();
+ }
+
+ /**
+ * Resolve the object by name.
+ *
+ * @param name
+ * the object name, .toString() is used to get the string
+ * representation.
+ */
+ public Object lookup(Name name) throws NamingException
+ {
+ return lookup(name.toString());
+ }
+
+ /**
+ * Resolve the object by name
+ *
+ * @param name the object name.
+ */
+ public Object lookup(String name) throws NamingException
+ {
+ try
+ {
+ return getRegistry().lookup(name);
+ }
+ catch (AccessException e)
+ {
+ throw new NamingException(e.toString());
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ catch (NotBoundException e)
+ {
+ throw new NameNotFoundException(name);
+ }
+ }
+}
diff --git a/gnu/javax/naming/jndi/url/rmi/ListBindingsEnumeration.java b/gnu/javax/naming/jndi/url/rmi/ListBindingsEnumeration.java
new file mode 100644
index 000000000..757e8bf59
--- /dev/null
+++ b/gnu/javax/naming/jndi/url/rmi/ListBindingsEnumeration.java
@@ -0,0 +1,97 @@
+/* ListBindingsEnumeration.java -- handles rmi: urls
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.naming.jndi.url.rmi;
+
+import java.rmi.registry.Registry;
+
+import javax.naming.NamingEnumeration;
+
+/**
+ * Iterates over bindings, obtaining values first from the binding list and then
+ * from the binding iterator.
+ *
+ * @author Audrius Meskauskas
+ */
+public class ListBindingsEnumeration extends RmiNamingEnumeration implements
+ NamingEnumeration
+{
+ /**
+ * The naming service, to resolve the objects.
+ */
+ Registry service;
+
+ /**
+ * Create the new enumeration
+ *
+ * @param bindings
+ * the list of the bound names
+ * @param aService
+ * the RMI naming service, used to get the bound values.
+ */
+ public ListBindingsEnumeration(String [] bindings,
+ Registry aService)
+ {
+ super(bindings);
+ service = aService;
+ }
+
+ /**
+ * Convert from the CORBA binding into the javax.naming binding. As the CORBA
+ * naming service binding does not contain the object itself, this method
+ * makes the additional calls to the naming service.
+ *
+ * @param binding
+ * the binding to convert
+ * @return the value, that must be returned by the {@link #next()}.
+ */
+ public Object convert(String binding)
+ {
+ try
+ {
+ Object object = service.lookup(binding);
+ return new javax.naming.Binding(binding, object);
+ }
+ catch (Exception e)
+ {
+ // Probably was removed by the concurent thread.
+ return null;
+ }
+ }
+
+}
diff --git a/gnu/javax/naming/jndi/url/rmi/ListEnumeration.java b/gnu/javax/naming/jndi/url/rmi/ListEnumeration.java
new file mode 100644
index 000000000..b4142c5e3
--- /dev/null
+++ b/gnu/javax/naming/jndi/url/rmi/ListEnumeration.java
@@ -0,0 +1,80 @@
+/* ListEnumeration.java -- handles rmi: urls
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.naming.jndi.url.rmi;
+
+import java.rmi.Remote;
+
+import javax.naming.NameClassPair;
+import javax.naming.NamingEnumeration;
+
+/**
+ * Iterates over name class pairs, obtaining values first from the binding list
+ * and then from the binding iterator.
+ *
+ * @author Audrius Meskauskas
+ */
+public class ListEnumeration extends RmiNamingEnumeration implements
+ NamingEnumeration
+{
+ /**
+ * Create the new enumeration
+ *
+ * @param bindings
+ * the array of the binding names, returned by the RMI registry.
+ */
+ public ListEnumeration(String [] bindings)
+ {
+ super(bindings);
+ }
+
+ /**
+ * Convert from the binding name into the {@link NameClassPair} that this
+ * enumeration should return.
+ *
+ * @param binding
+ * the binding to convert
+ * @return the value, that must be returned by the {@link #next()}.
+ */
+ public Object convert(String binding)
+ {
+ NameClassPair pair = new NameClassPair(binding, Remote.class.getName());
+ return pair;
+ }
+
+}
diff --git a/gnu/javax/naming/jndi/url/rmi/RmiContinuation.java b/gnu/javax/naming/jndi/url/rmi/RmiContinuation.java
new file mode 100644
index 000000000..29eb61b4b
--- /dev/null
+++ b/gnu/javax/naming/jndi/url/rmi/RmiContinuation.java
@@ -0,0 +1,594 @@
+/* RmiContinuation.java -- RMI naming context
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.naming.jndi.url.rmi;
+
+import java.rmi.AccessException;
+import java.rmi.AlreadyBoundException;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.naming.CommunicationException;
+import javax.naming.Context;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NameNotFoundException;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.OperationNotSupportedException;
+
+/**
+ * The implementation of the RMI URL context. This context connects
+ *
+ * @author Audrius Meskauskas
+ */
+public class RmiContinuation implements Context
+{
+ /**
+ * The default registry location.
+ */
+ public static final String DEFAULT_REGISTRY_LOCATION = "rmi://localhost:1099";
+
+ /**
+ * The local or remote RMI registry, performing the actual work for this
+ * context.
+ */
+ Registry registry;
+
+ /**
+ * The properties.
+ */
+ Properties properties;
+
+ /**
+ * The flag, indicating, that the lookup methods were called before.
+ * If the lookup methods were called before, the existing ORB cannot be
+ * destroyed, as references to the existing objects will become
+ * unfunctional.
+ */
+ boolean lookupCalled;
+
+ /**
+ * Add new environment property to the environment of this context. Both name
+ * and value of the new property must not be null. If the property is already
+ * defined, is current value is replaced by the propVal. This method replaces
+ * the registry. The new registry will be lazily instantiated on the first
+ * call.
+ *
+ * @param key
+ * the name of the new property
+ * @param value
+ * the value of the new property
+ * @return the previous value of this property or null if the property has not
+ * been previously defined
+ */
+ public Object addToEnvironment(String key, Object value)
+ {
+ removeRegistry();
+ if (key == null || value == null)
+ throw new NullPointerException();
+ return properties.put(key, value);
+ }
+
+ /**
+ * Returns the environment, associated with this naming context. The returned
+ * table should never be modified by the caller (the registry would not be updated
+ * in such case). Use {@link #addToEnvironment} and
+ * {@link #removeFromEnvironment} to modify the environement, if needed.
+ *
+ * @return the table, representing the environment of this context
+ * @throws NamingException
+ */
+ public Hashtable getEnvironment() throws NamingException
+ {
+ return properties;
+ }
+
+ /**
+ * Removes the property with the given name from the environment. Returns
+ * without action if this property is not defined. Replaces the ORB,
+ * constructing the new ORB with the changes set of properties (you can
+ * replace the CORBA implementation provider, for instance). The new ORB will
+ * be lazily instantiated on the first call.
+ *
+ * @param propName
+ * the name of the property being removed.
+ * @return the value of the property that has been removed or null if the
+ * property was not defined.
+ * @throws NamingException
+ */
+ public Object removeFromEnvironment(String propName) throws NamingException
+ {
+ removeRegistry();
+ return properties.remove(propName);
+ }
+
+ /**
+ * Remove the current registry reference.
+ */
+ public void removeRegistry()
+ {
+ registry = null;
+ }
+
+ /**
+ * Get the cached or new registry reference.
+ *
+ * @return the registry reference, either cached or new.
+ */
+ public Registry getRegistry() throws NamingException
+ {
+ if (registry == null)
+ {
+ String address = properties.getProperty(Context.PROVIDER_URL,
+ DEFAULT_REGISTRY_LOCATION);
+
+ // The format like rmi://localhost:1099 is expected. Parse.
+ if (!address.startsWith("rmi://"))
+ throw new InvalidNameException(address);
+
+ String a = address.substring("rmi://".length());
+
+ // The colon, if present, indicates the start of the port number.
+ int colon = a.lastIndexOf(':');
+ int port;
+
+ try
+ {
+ if (colon >=0)
+ {
+ port = Integer.parseInt(a.substring(colon+1));
+ a = a.substring(0, colon);
+ }
+ else
+ port = Registry.REGISTRY_PORT;
+ }
+ catch (NumberFormatException e1)
+ {
+ throw new InvalidNameException(address);
+ }
+
+ try
+ {
+ registry = LocateRegistry.getRegistry(a, port);
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ }
+ return registry;
+ }
+
+ /**
+ * Create the rmi url context that works, talking with the given RMI registry.
+ *
+ * @param props
+ * the properties for this context
+ */
+ public RmiContinuation(Map props)
+ {
+ properties = new Properties();
+ if (props != null)
+ properties.putAll(props);
+ }
+
+ /**
+ * Bind the given name into this context. The .toString() is called to
+ * convert into the string representation, required by RMI registry.
+ *
+ * @throws NamingException if the object is not an instance of Remote
+ */
+ public void bind(Name name, Object obj) throws NamingException
+ {
+ bind(name.toString(), obj);
+ }
+
+ /**
+ * Bind the given name into this context.
+ */
+ public void bind(String name, Object obj) throws NamingException
+ {
+ try
+ {
+ getRegistry().bind(name, (Remote) obj);
+ }
+ catch (AccessException e)
+ {
+ throw new NamingException("access:"+e.toString());
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ catch (AlreadyBoundException e)
+ {
+ throw new NameAlreadyBoundException(name);
+ }
+ catch (ClassCastException c)
+ {
+ throw new NamingException("Only Remote can be bound:"
+ + obj.getClass().getName());
+ }
+ }
+
+ /**
+ * Not supported.
+ */
+ public Name composeName(Name name, Name prefix) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Not supported.
+ */
+ public String composeName(String name, String prefix) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Subcontexts are not supporte by RMI registry. The only supported case is an
+ * empty name (returns the cloned instance of self).
+ */
+ public Context createSubcontext(Name name) throws NamingException
+ {
+ if (name.size() == 0)
+ return new RmiContinuation(properties);
+ else
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Subcontexts are not supporte by RMI registry. The only supported case is an
+ * empty name (returns the cloned instance of self).
+ */
+ public Context createSubcontext(String name) throws NamingException
+ {
+ if (name.length() == 0)
+ return new RmiContinuation(properties);
+ else
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Subcontexts are not supporte by RMI registry.
+ */
+ public void destroySubcontext(Name name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Subcontexts are not supporte by RMI registry.
+ */
+ public void destroySubcontext(String name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Returns the naming service URL, same that was passed vie
+ * {@link Context#PROVIDER_URL}.
+ */
+ public String getNameInNamespace() throws NamingException
+ {
+ return properties.getProperty(Context.PROVIDER_URL,
+ DEFAULT_REGISTRY_LOCATION);
+ }
+
+ /**
+ * Not supported, this context never parses any names.
+ */
+ public NameParser getNameParser(Name name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Not supported, this context never parses any names.
+ */
+ public NameParser getNameParser(String name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * List existing bindings of this context (the parameter must be empty name,
+ * indicating the root context). The class name of the returned name class
+ * pairs is "Remote", as this "quick preview" method should probably not call
+ * the naming service again. Use listBindings if more details are required.
+ */
+ public NamingEnumeration list(Name name) throws NamingException
+ {
+ if (name.size() > 0)
+ throw new OperationNotSupportedException("Only empty name is accepted");
+ return list("");
+ }
+
+ /**
+ * List existing bindings of this context (the parameter must be empty string,
+ * indicating the root context). The class name of the returned name class
+ * pairs is "Remote", as this "quick preview" method should probably not call
+ * the naming service again. Use listBindings if more details are required.
+ */
+ public NamingEnumeration list(String name) throws NamingException
+ {
+ if (name.length() > 0)
+ throw new OperationNotSupportedException("Only empty name is accepted");
+
+ try
+ {
+ return new ListEnumeration(getRegistry().list());
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ /**
+ * List existing bindings of this context (the parameter must be empty name,
+ * indicating the root context).
+ */
+ public NamingEnumeration listBindings(Name name) throws NamingException
+ {
+ if (name.size() > 0)
+ throw new OperationNotSupportedException("Only empty name is accepted");
+ return listBindings("");
+ }
+
+ /**
+ * List existing bindings of this context (the parameter must be empty name,
+ * indicating the root context).
+ */
+ public NamingEnumeration listBindings(String name) throws NamingException
+ {
+ if (name.length() > 0)
+ throw new OperationNotSupportedException("Only empty name is accepted");
+
+ try
+ {
+ Registry r = getRegistry();
+ return new ListBindingsEnumeration(r.list(), r);
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ /**
+ * Not supported.
+ */
+ public Object lookupLink(Name name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Not supported.
+ */
+ public Object lookupLink(String name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Rebinds this object.
+ *
+ * @param name
+ * the object name (.toString()) is used to convert into string
+ * representation.
+ * @param obj
+ * object (must be an instance of Remote).
+ */
+ public void rebind(Name name, Object obj) throws NamingException
+ {
+ rebind(name.toString(), obj);
+ }
+
+ /**
+ * Rebinds this object.
+ *
+ * @param name
+ * the object name.
+ * @param obj
+ * object (must be an instance of Remote).
+ */
+ public void rebind(String name, Object obj) throws NamingException
+ {
+ try
+ {
+ getRegistry().rebind(name, (Remote) obj);
+ }
+ catch (AccessException e)
+ {
+ throw new NamingException("access:"+e.toString());
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ catch (ClassCastException c)
+ {
+ throw new NamingException("Only Remote can be bound:"
+ + obj.getClass().getName());
+ }
+ }
+
+ /**
+ * Renames the object. If the new name is already bound in the given context,
+ * the {@link AlreadyBoundException} is thrown and the oldName binding is
+ * preserved.
+ */
+ public void rename(Name oldName, Name newName) throws NamingException
+ {
+ rename(oldName.toString(), newName.toString());
+ }
+
+ /**
+ * Renames the object. If the new name is already bound in the given context,
+ * the {@link AlreadyBoundException} is thrown and the oldName binding is
+ * preserved.
+ */
+ public synchronized void rename(String oldName, String newName)
+ throws NamingException
+ {
+ try
+ {
+ Registry r = getRegistry();
+ Remote object = r.lookup(oldName);
+ r.unbind(oldName);
+ try
+ {
+ r.bind(newName, object);
+ }
+ catch (AlreadyBoundException e)
+ {
+ // Bind it back.
+ try
+ {
+ r.bind(oldName, object);
+ }
+ catch (AlreadyBoundException e1)
+ {
+ // We have just removed this name.
+ throw new InternalError();
+ }
+ throw new NameAlreadyBoundException(newName);
+ }
+ }
+ catch (AccessException e)
+ {
+ throw new NamingException(e.toString());
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ catch (NotBoundException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ }
+
+ /**
+ * Unbind the object.
+ */
+ public void unbind(Name name) throws NamingException
+ {
+ unbind(name.toString());
+ }
+
+ /**
+ * Unbind the object.
+ */
+ public void unbind(String name) throws NamingException
+ {
+ try
+ {
+ getRegistry().unbind(name);
+ }
+ catch (AccessException e)
+ {
+ throw new NamingException(e.toString());
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ catch (NotBoundException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ }
+
+ /**
+ * Release the associated resources.
+ */
+ public void close() throws NamingException
+ {
+ removeRegistry();
+ }
+
+ /**
+ * Resolve the object by name.
+ *
+ * @param name
+ * the object name, .toString() is used to get the string
+ * representation.
+ */
+ public Object lookup(Name name) throws NamingException
+ {
+ return lookup(name.toString());
+ }
+
+ /**
+ * Resolve the object by name
+ *
+ * @param name the object name.
+ */
+ public Object lookup(String name) throws NamingException
+ {
+ try
+ {
+ return getRegistry().lookup(name);
+ }
+ catch (AccessException e)
+ {
+ throw new NamingException(e.toString());
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ catch (NotBoundException e)
+ {
+ throw new NameNotFoundException(name);
+ }
+ }
+}
diff --git a/gnu/javax/naming/jndi/url/rmi/RmiNamingEnumeration.java b/gnu/javax/naming/jndi/url/rmi/RmiNamingEnumeration.java
new file mode 100644
index 000000000..6d88cccef
--- /dev/null
+++ b/gnu/javax/naming/jndi/url/rmi/RmiNamingEnumeration.java
@@ -0,0 +1,130 @@
+/* RmiNamingEnumeration.java -- handles rmi: urls
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.naming.jndi.url.rmi;
+
+import java.util.NoSuchElementException;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+
+/**
+ * Iterates over name class pairs, obtaining values first from the binding list
+ * and then from the binding iterator.
+ *
+ * @author Audrius Meskauskas
+ */
+public abstract class RmiNamingEnumeration implements NamingEnumeration
+{
+ /**
+ * The array of bindings, returned at once.
+ */
+ String[] list;
+
+ /**
+ * The position of the element in the binding list, that must be returned
+ * during the subsequent call of the next(). If this field is grater or equal
+ * to the lenght of the list, the subsequent values must be requested from the
+ * iterator.
+ */
+ int p;
+
+ RmiNamingEnumeration(String[] bindingList)
+ {
+ list = bindingList;
+ }
+
+ /**
+ * Convert from the CORBA binding into that this enumeration should return.
+ *
+ * @param binding
+ * the binding to convert
+ * @return the value, that must be returned by the {@link #next()}.
+ */
+ public abstract Object convert(String binding);
+
+ /**
+ * Checks if there are more elements to return.
+ *
+ * @throws NamingException
+ * never
+ */
+ public boolean hasMore() throws NamingException
+ {
+ return hasMoreElements();
+ }
+
+ /**
+ * Returns the next element.
+ *
+ * @throws NamingException
+ * never
+ */
+ public Object next() throws NamingException
+ {
+ return nextElement();
+ }
+
+ /**
+ * Checks if there are more elements to return.
+ */
+ public boolean hasMoreElements()
+ {
+ return p < list.length;
+ }
+
+ /**
+ * Returns the next element.
+ */
+ public Object nextElement()
+ {
+ if (p < list.length)
+ return convert(list[p++]);
+ else
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * Nothing to do in this method.
+ */
+ public void close()
+ {
+ // Nothing to do here.
+ }
+
+}
diff --git a/gnu/javax/naming/jndi/url/rmi/rmiURLContext.java b/gnu/javax/naming/jndi/url/rmi/rmiURLContext.java
new file mode 100644
index 000000000..a17ce026b
--- /dev/null
+++ b/gnu/javax/naming/jndi/url/rmi/rmiURLContext.java
@@ -0,0 +1,637 @@
+/* rmiURLContext.java -- RMI naming context
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.naming.jndi.url.rmi;
+
+import java.rmi.AccessException;
+import java.rmi.AlreadyBoundException;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+import java.util.WeakHashMap;
+
+import javax.naming.CommunicationException;
+import javax.naming.Context;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NameNotFoundException;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.OperationNotSupportedException;
+
+/**
+ * The implementation of the RMI URL context. This context connects
+ *
+ * @author Audrius Meskauskas
+ */
+public class rmiURLContext implements Context
+{
+ /**
+ * The default registry location.
+ */
+ public static final String DEFAULT_REGISTRY_LOCATION = "rmi://localhost:1099";
+
+ /**
+ * The registry cache, maps the registry URL's to they instances. The
+ * obtained registries are reused, as newly obtaining them may cause the
+ * resource leak.
+ */
+ static WeakHashMap registryCache = new WeakHashMap();
+
+ /**
+ * The properties.
+ */
+ Properties properties;
+
+ /**
+ * The flag, indicating, that the lookup methods were called before.
+ * If the lookup methods were called before, the existing ORB cannot be
+ * destroyed, as references to the existing objects will become
+ * unfunctional.
+ */
+ boolean lookupCalled;
+
+ /**
+ * Add new environment property to the environment of this context. Both name
+ * and value of the new property must not be null. If the property is already
+ * defined, is current value is replaced by the propVal. This method replaces
+ * the registry. The new registry will be lazily instantiated on the first
+ * call.
+ *
+ * @param key
+ * the name of the new property
+ * @param value
+ * the value of the new property
+ * @return the previous value of this property or null if the property has not
+ * been previously defined
+ */
+ public Object addToEnvironment(String key, Object value)
+ {
+ if (key == null || value == null)
+ throw new NullPointerException();
+ return properties.put(key, value);
+ }
+
+ /**
+ * Returns the environment, associated with this naming context. The returned
+ * table should never be modified by the caller (the registry would not be updated
+ * in such case). Use {@link #addToEnvironment} and
+ * {@link #removeFromEnvironment} to modify the environement, if needed.
+ *
+ * @return the table, representing the environment of this context
+ * @throws NamingException
+ */
+ public Hashtable getEnvironment() throws NamingException
+ {
+ return properties;
+ }
+
+ /**
+ * Removes the property with the given name from the environment. Returns
+ * without action if this property is not defined. Replaces the ORB,
+ * constructing the new ORB with the changes set of properties (you can
+ * replace the CORBA implementation provider, for instance). The new ORB will
+ * be lazily instantiated on the first call.
+ *
+ * @param propName
+ * the name of the property being removed.
+ * @return the value of the property that has been removed or null if the
+ * property was not defined.
+ * @throws NamingException
+ */
+ public Object removeFromEnvironment(String propName) throws NamingException
+ {
+ return properties.remove(propName);
+ }
+
+ /**
+ * Get the cached or new registry reference.
+ *
+ * @return the registry reference, either cached or new.
+ */
+ public Registry getRegistry(String netAddress) throws NamingException
+ {
+ Registry registry;
+
+ synchronized (registryCache)
+ {
+ registry = (Registry) registryCache.get(netAddress);
+ }
+
+ if (registry == null)
+ {
+ // The colon, if present, indicates the start of the port number.
+ int colon = netAddress.lastIndexOf(':');
+ int port;
+
+ try
+ {
+ if (colon >= 0)
+ {
+ port = Integer.parseInt(netAddress.substring(colon + 1));
+ netAddress = netAddress.substring(0, colon);
+ }
+ else
+ port = Registry.REGISTRY_PORT;
+ }
+ catch (NumberFormatException e1)
+ {
+ throw new InvalidNameException(netAddress);
+ }
+
+ try
+ {
+ registry = LocateRegistry.getRegistry(netAddress, port);
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+
+ synchronized (registryCache)
+ {
+ registryCache.put(netAddress, registry);
+ }
+ }
+ return registry;
+ }
+
+ /**
+ * Create the rmi url context that works, talking with the given RMI registry.
+ *
+ * @param props
+ * the properties for this context
+ */
+ public rmiURLContext(Map props)
+ {
+ properties = new Properties();
+ if (props != null)
+ properties.putAll(props);
+ }
+
+ /**
+ * Bind the given name into this context. The .toString() is called to
+ * convert into the string representation, required by RMI registry.
+ *
+ * @throws NamingException if the object is not an instance of Remote
+ */
+ public void bind(Name name, Object obj) throws NamingException
+ {
+ bind(name.toString(), obj);
+ }
+
+ /**
+ * Bind the given name into this context.
+ */
+ public void bind(String name, Object obj) throws NamingException
+ {
+ try
+ {
+ String [] n = split(name);
+ getRegistry(n[0]).bind(n[1], (Remote) obj);
+ }
+ catch (AccessException e)
+ {
+ throw new NamingException("access:"+e.toString());
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ catch (AlreadyBoundException e)
+ {
+ throw new NameAlreadyBoundException(name);
+ }
+ catch (ClassCastException c)
+ {
+ throw new NamingException("Only Remote can be bound:"
+ + obj.getClass().getName());
+ }
+ }
+
+ /**
+ * Not supported.
+ */
+ public Name composeName(Name name, Name prefix) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Not supported.
+ */
+ public String composeName(String name, String prefix) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Subcontexts are not supporte by RMI registry. The only supported case is an
+ * empty name (returns the cloned instance of self).
+ */
+ public Context createSubcontext(Name name) throws NamingException
+ {
+ if (name.size() == 0)
+ return new rmiURLContext(properties);
+ else
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Subcontexts are not supporte by RMI registry. The only supported case is an
+ * empty name (returns the cloned instance of self).
+ */
+ public Context createSubcontext(String name) throws NamingException
+ {
+ if (name.length() == 0)
+ return new rmiURLContext(properties);
+ else
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Subcontexts are not supporte by RMI registry.
+ */
+ public void destroySubcontext(Name name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Subcontexts are not supporte by RMI registry.
+ */
+ public void destroySubcontext(String name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Returns the naming service URL, same that was passed vie
+ * {@link Context#PROVIDER_URL}.
+ */
+ public String getNameInNamespace() throws NamingException
+ {
+ return properties.getProperty(Context.PROVIDER_URL,
+ DEFAULT_REGISTRY_LOCATION);
+ }
+
+ /**
+ * Not supported, this context never parses any names.
+ */
+ public NameParser getNameParser(Name name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * Not supported, this context never parses any names.
+ */
+ public NameParser getNameParser(String name) throws NamingException
+ {
+ throw new OperationNotSupportedException();
+ }
+
+ /**
+ * List existing bindings of this context (the parameter must be empty name,
+ * indicating the root context). The class name of the returned name class
+ * pairs is "Remote", as this "quick preview" method should probably not call
+ * the naming service again. Use listBindings if more details are required.
+ */
+ public NamingEnumeration list(Name name) throws NamingException
+ {
+ return list(name);
+ }
+
+ /**
+ * List existing bindings of thie given registry.The class name of the
+ * returned name class pairs is "Remote", as this "quick preview" method
+ * should probably not call the naming service again. Use listBindings if more
+ * details are required.
+ */
+ public NamingEnumeration list(String name) throws NamingException
+ {
+ try
+ {
+ String [] n = split(name);
+ if (n[1].length() > 0)
+ throw new InvalidNameException(name+", the name part must be empty");
+ return new ListEnumeration(getRegistry(n[0]).list());
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ /**
+ * List existing bindings of this context (the parameter must be empty name,
+ * indicating the root context).
+ */
+ public NamingEnumeration listBindings(Name name) throws NamingException
+ {
+ return listBindings(name.toString());
+ }
+
+ /**
+ * List existing bindings of this context.
+ */
+ public NamingEnumeration listBindings(String name) throws NamingException
+ {
+ try
+ {
+ String [] n = split(name);
+ if (n[1].length() > 0)
+ throw new InvalidNameException(name+", the name part must be empty");
+
+ Registry r = getRegistry(n[0]);
+ return new ListBindingsEnumeration(r.list(), r);
+ }
+ catch (Exception e)
+ {
+ throw new NamingException(e.toString());
+ }
+ }
+
+ /**
+ * Returns the naming service context under the given address, wrapped as
+ * Context.
+ */
+ public Object lookupLink(Name name) throws NamingException
+ {
+ return lookupLink(name.toString());
+ }
+
+ /**
+ * Returns the naming service context under the given address,
+ * wrapped as Context.
+ */
+ public Object lookupLink(String name) throws NamingException
+ {
+ return new ContextContinuation(properties, getRegistry(name));
+ }
+
+ /**
+ * Rebinds this object.
+ *
+ * @param name
+ * the object name (.toString()) is used to convert into string
+ * representation.
+ * @param obj
+ * object (must be an instance of Remote).
+ */
+ public void rebind(Name name, Object obj) throws NamingException
+ {
+ rebind(name.toString(), obj);
+ }
+
+ /**
+ * Rebinds this object.
+ *
+ * @param name
+ * the object name.
+ * @param obj
+ * object (must be an instance of Remote).
+ */
+ public void rebind(String name, Object obj) throws NamingException
+ {
+ try
+ {
+ String [] n = split(name);
+ getRegistry(n[0]).rebind(n[1], (Remote) obj);
+ }
+ catch (AccessException e)
+ {
+ throw new NamingException("access:"+e.toString());
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ catch (ClassCastException c)
+ {
+ throw new NamingException("Only Remote can be bound:"
+ + obj.getClass().getName());
+ }
+ }
+
+ /**
+ * Renames the object. If the new name is already bound in the given context,
+ * the {@link AlreadyBoundException} is thrown and the oldName binding is
+ * preserved.
+ */
+ public void rename(Name oldName, Name newName) throws NamingException
+ {
+ rename(oldName.toString(), newName.toString());
+ }
+
+ /**
+ * Renames the object. If the new name is already bound in the given context,
+ * the {@link AlreadyBoundException} is thrown and the oldName binding is
+ * preserved.
+ */
+ public synchronized void rename(String oldName, String newName)
+ throws NamingException
+ {
+ try
+ {
+ String [] n = split(oldName);
+ Registry r = getRegistry(n[0]);
+ Remote object = r.lookup(n[1]);
+ r.unbind(oldName);
+ try
+ {
+ String [] n2 = split(newName);
+ Registry r2 = getRegistry(n2[0]);
+ r2.bind(n2[1], object);
+ }
+ catch (AlreadyBoundException e)
+ {
+ // Bind it back.
+ try
+ {
+ r.bind(oldName, object);
+ }
+ catch (AlreadyBoundException e1)
+ {
+ // We have just removed this name.
+ throw new InternalError();
+ }
+ throw new NameAlreadyBoundException(newName);
+ }
+ }
+ catch (AccessException e)
+ {
+ throw new NamingException(e.toString());
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ catch (NotBoundException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ }
+
+ /**
+ * Unbind the object.
+ */
+ public void unbind(Name name) throws NamingException
+ {
+ unbind(name.toString());
+ }
+
+ /**
+ * Unbind the object.
+ */
+ public void unbind(String name) throws NamingException
+ {
+ try
+ {
+ String [] n = split(name);
+ getRegistry(n[0]).unbind(n[1]);
+ }
+ catch (AccessException e)
+ {
+ throw new NamingException(e.toString());
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ catch (NotBoundException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ }
+
+ /**
+ * Release the associated resources.
+ */
+ public void close() throws NamingException
+ {
+ }
+
+ /**
+ * Resolve the object by name.
+ *
+ * @param name
+ * the object name, .toString() is used to get the string
+ * representation.
+ */
+ public Object lookup(Name name) throws NamingException
+ {
+ return lookup(name.toString());
+ }
+
+ /**
+ * Resolve the object by name
+ *
+ * @param name the object name.
+ */
+ public Object lookup(String name) throws NamingException
+ {
+ try
+ {
+ String [] n = split(name);
+ return getRegistry(n[0]).lookup(n[1]);
+ }
+ catch (AccessException e)
+ {
+ throw new NamingException(e.toString());
+ }
+ catch (RemoteException e)
+ {
+ throw new CommunicationException(e.toString());
+ }
+ catch (NotBoundException e)
+ {
+ throw new NameNotFoundException(name);
+ }
+ }
+
+ /**
+ * Split the given rmi address into the network address and naming service
+ * name.
+ *
+ * @param address
+ * the address to split
+ * @return the two member array, lower being the network address of the naming
+ * service and upper being the naming service name
+ * @throws NamingException
+ * if the name is invalid
+ */
+ public String[] split(String address) throws NamingException
+ {
+ // The format like rmi://localhost:1099/name is expected. Parse.
+ if (!address.startsWith("rmi://"))
+ throw new InvalidNameException(
+ address
+ + " should be like 'rmi://localhost:1099/name'");
+
+ String a = address.substring("rmi://".length());
+
+ // The suffix starts after the first slash from the rmi://
+ int sfx = a.indexOf('/');
+
+ // Handle the possible escape
+ while (sfx > 0 && a.charAt(sfx - 1) == '\\')
+ sfx = a.indexOf('/', sfx + 1);
+
+ String net;
+ String name;
+ if (sfx >= 0)
+ {
+ net = a.substring(0, sfx);
+ name = a.substring(sfx + 1);
+ }
+ else
+ {
+ net = a;
+ name = "";
+ }
+
+ return new String[] { net, name };
+ }
+}
diff --git a/gnu/javax/naming/jndi/url/rmi/rmiURLContextFactory.java b/gnu/javax/naming/jndi/url/rmi/rmiURLContextFactory.java
new file mode 100644
index 000000000..593845327
--- /dev/null
+++ b/gnu/javax/naming/jndi/url/rmi/rmiURLContextFactory.java
@@ -0,0 +1,66 @@
+/* rmiURLContextFactory.java -- handles RMI naming context
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.naming.jndi.url.rmi;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.spi.ObjectFactory;
+
+/**
+ * Find the RMI URL context. This factory checks the Context.PROVIDER_URL
+ * property for the address of the RMI naming service and creates the
+ * context that operates talking with this naming service. If such property
+ * is missing, "rmi://localhost:1099" is assumed.
+ *
+ * @author Audrius Meskauskas (audriusa@Bioinformatics.org)
+ */
+public class rmiURLContextFactory implements ObjectFactory
+{
+
+ /**
+ * Create a new instance of the context.
+ */
+ public Object getObjectInstance(Object refObj, Name name, Context nameCtx,
+ Hashtable environment)
+ {
+ return new rmiURLContext(environment);
+ }
+
+}
diff --git a/gnu/javax/print/ipp/IppRequest.java b/gnu/javax/print/ipp/IppRequest.java
index ccfa9b272..05a6faae7 100644
--- a/gnu/javax/print/ipp/IppRequest.java
+++ b/gnu/javax/print/ipp/IppRequest.java
@@ -794,7 +794,7 @@ public class IppRequest
alreadySent = true;
- OutputStream stream = stream = connection.getOutputStream();
+ OutputStream stream = connection.getOutputStream();
DataOutputStream out = new DataOutputStream(stream);
// the header 8 bytes long
@@ -849,7 +849,7 @@ public class IppRequest
// own thread.
connection.setConnectTimeout( timeout );
- int responseCode = responseCode = connection.getResponseCode();
+ int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK)
{
diff --git a/gnu/javax/security/auth/callback/AbstractCallbackHandler.java b/gnu/javax/security/auth/callback/AbstractCallbackHandler.java
index eeedf2605..5144f58ea 100644
--- a/gnu/javax/security/auth/callback/AbstractCallbackHandler.java
+++ b/gnu/javax/security/auth/callback/AbstractCallbackHandler.java
@@ -83,65 +83,102 @@ public abstract class AbstractCallbackHandler implements CallbackHandler
this.name = name;
}
- // Class methods.
- // -------------------------------------------------------------------------
-
+ /**
+ * Create an instance of <code>CallbackHandler</code> of the designated
+ * <code>type</code> from the first Security Provider which offers it.
+ *
+ * @param type the type of callback handler to create.
+ * @return a newly created instance of <code>ClassbackHandler</code>.
+ * @throws NoSuchAlgorithmException if no security provider is found to offer
+ * an implementation of <code>CallbackHandler</code> of the
+ * designated <code>type</code>.
+ */
public static CallbackHandler getInstance(String type)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(type, p[i]);
- }
- catch (NoSuchAlgorithmException ignored)
- {
- }
- }
+ try
+ {
+ return getInstance(type, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(type);
}
+ /**
+ * Create an instance of <code>CallbackHandler</code> of the designated
+ * <code>type</code> from the named security <code>provider</code>.
+ *
+ * @param type the type of callback handler to create.
+ * @param provider a named security provider to use.
+ * @return a newly created instance of <code>ClassbackHandler</code>.
+ * @throws NoSuchAlgorithmException if no security provider is found to offer
+ * an implementation of <code>CallbackHandler</code> of the
+ * designated <code>type</code>.
+ * @throws IllegalArgumentException if either <code>type</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>type</code> is an empty string.
+ */
public static CallbackHandler getInstance(String type, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
- {
- throw new NoSuchProviderException(provider);
- }
+ throw new NoSuchProviderException(provider);
return getInstance(type, p);
}
+ /**
+ * Create an instance of <code>CallbackHandler</code> of the designated
+ * <code>type</code> from the designated security <code>provider</code>.
+ *
+ * @param type the type of callback handler to create.
+ * @param provider a security provider to use.
+ * @return a newly created instance of <code>ClassbackHandler</code>.
+ * @throws NoSuchAlgorithmException if no security provider is found to offer
+ * an implementation of <code>CallbackHandler</code> of the
+ * designated <code>type</code>.
+ * @throws IllegalArgumentException if either <code>type</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>type</code> is an empty string.
+ */
public static CallbackHandler getInstance(String type, Provider provider)
throws NoSuchAlgorithmException
{
+ StringBuilder sb = new StringBuilder("CallbackHandler of type [")
+ .append(type).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
return (CallbackHandler) Engine.getInstance(SERVICE, type, provider);
}
- catch (InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- Throwable cause = ite.getCause();
+ cause = x.getCause();
if (cause instanceof NoSuchAlgorithmException)
throw (NoSuchAlgorithmException) cause;
- NoSuchAlgorithmException nsae = new NoSuchAlgorithmException(type);
- if (cause != null)
- nsae.initCause (cause);
- throw nsae;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- NoSuchAlgorithmException nsae = new NoSuchAlgorithmException(type);
- nsae.initCause (cce);
- throw nsae;
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // -------------------------------------------------------------------------
-
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException
{
diff --git a/gnu/javax/sound/sampled/AU/AUReader.java b/gnu/javax/sound/sampled/AU/AUReader.java
new file mode 100644
index 000000000..c9035df73
--- /dev/null
+++ b/gnu/javax/sound/sampled/AU/AUReader.java
@@ -0,0 +1,212 @@
+/* AUReader.java -- Read AU files.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.sound.sampled.AU;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.UnsupportedAudioFileException;
+import javax.sound.sampled.spi.AudioFileReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.BufferedInputStream;
+import java.io.InputStream;
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.nio.ByteBuffer;
+
+public class AUReader extends AudioFileReader
+{
+ private static class AUHeader
+ {
+ // Magic number identifying the file. '.snd'
+ private static final int MAGIC = 0x2e736e64;
+
+ public static final int SIZE = 24; // size of the header
+
+ // Encoding types
+ public static final int ULAW = 1; // 8-bit u-law
+ public static final int PCM8 = 2; // 8-bit PCM
+ public static final int PCM16 = 3; // 16-bit PCM
+ public static final int PCM24 = 4; // 24-bit PCM
+ public static final int PCM32 = 5; // 32-bit PCM
+ public static final int IEEE32 = 6; // 32-bit IEEE f.p.
+ public static final int IEEE64 = 7; // 64-bit IEEE f.p.
+ public static final int G721 = 23;
+ public static final int G722 = 24;
+ public static final int G723 = 25;
+ public static final int G723_5BIT = 26;
+ public static final int ALAW = 27; // 8-bit a-law
+
+ // Header data.
+ public int headerSize;
+ public int fileSize; // this value may not be set.
+ public int encoding;
+ public int sampleRate;
+ public int channels;
+ public int sampleSizeInBits;
+
+ public AUHeader(InputStream stream)
+ throws IOException, UnsupportedAudioFileException
+ {
+ byte[] hdr = new byte[24];
+ stream.read( hdr );
+ ByteBuffer buf = ByteBuffer.wrap(hdr);
+
+ if( buf.getInt() != MAGIC )
+ throw new UnsupportedAudioFileException("Not an AU format audio file.");
+ headerSize = buf.getInt();
+ fileSize = buf.getInt();
+ encoding = buf.getInt();
+ sampleRate = buf.getInt();
+ channels = buf.getInt();
+
+ switch(encoding)
+ {
+ case ULAW:
+ case PCM8:
+ case ALAW:
+ sampleSizeInBits = 8;
+ break;
+ case PCM16:
+ sampleSizeInBits = 16;
+ break;
+ case PCM24:
+ sampleSizeInBits = 24;
+ break;
+ case PCM32:
+ sampleSizeInBits = 32;
+ break;
+ default: // other types exist but are not supported. Yet.
+ throw new UnsupportedAudioFileException("Unsupported encoding.");
+ }
+ }
+
+ public AudioFormat getAudioFormat()
+ {
+ AudioFormat.Encoding encType = AudioFormat.Encoding.PCM_SIGNED;
+ if(encoding == 1)
+ encType = AudioFormat.Encoding.ULAW;
+ if(encoding == 27)
+ encType = AudioFormat.Encoding.ALAW;
+
+ return new AudioFormat(encType,
+ (float)sampleRate,
+ sampleSizeInBits,
+ channels,
+ (sampleSizeInBits >> 3) * channels,
+ (float)sampleRate,
+ true);
+ }
+
+ public AudioFileFormat getAudioFileFormat()
+ {
+ return new AudioFileFormat(new AUFormatType(),
+ getAudioFormat(),
+ AudioSystem.NOT_SPECIFIED);
+ }
+ }
+
+ public static class AUFormatType extends AudioFileFormat.Type
+ {
+ public AUFormatType()
+ {
+ super("AU", ".au");
+ }
+ }
+
+ public AudioFileFormat getAudioFileFormat(File file)
+ throws IOException, UnsupportedAudioFileException
+ {
+ return getAudioFileFormat(new FileInputStream(file));
+ }
+
+ public AudioFileFormat getAudioFileFormat(InputStream stream)
+ throws IOException, UnsupportedAudioFileException
+ {
+ if(!stream.markSupported())
+ throw new IOException("Stream must support marking.");
+
+ stream.mark(25);
+ AUHeader header = new AUHeader(stream);
+ stream.reset();
+
+ return header.getAudioFileFormat();
+ }
+
+ public AudioFileFormat getAudioFileFormat(URL url)
+ throws IOException, UnsupportedAudioFileException
+ {
+ return getAudioFileFormat(new BufferedInputStream(url.openStream()));
+ }
+
+ public AudioInputStream getAudioInputStream(File file)
+ throws IOException, UnsupportedAudioFileException
+ {
+ InputStream stream = new FileInputStream(file);
+ long length = file.length();
+
+ AUHeader header = new AUHeader( stream );
+ if( header.headerSize > AUHeader.SIZE )
+ stream.skip(header.headerSize - AUHeader.SIZE);
+
+ length -= header.headerSize;
+
+ return new AudioInputStream(stream, header.getAudioFormat(), length);
+ }
+
+ public AudioInputStream getAudioInputStream(InputStream stream)
+ throws IOException, UnsupportedAudioFileException
+ {
+ AUHeader header = new AUHeader( stream );
+ if( header.headerSize > AUHeader.SIZE )
+ stream.skip(header.headerSize - AUHeader.SIZE);
+
+ return new AudioInputStream(stream, header.getAudioFormat(),
+ AudioSystem.NOT_SPECIFIED);
+ }
+
+ public AudioInputStream getAudioInputStream(URL url)
+ throws IOException, UnsupportedAudioFileException
+ {
+ return getAudioInputStream(new BufferedInputStream(url.openStream()));
+ }
+}
+
diff --git a/gnu/javax/sound/sampled/WAV/WAVReader.java b/gnu/javax/sound/sampled/WAV/WAVReader.java
new file mode 100644
index 000000000..0cf3c1377
--- /dev/null
+++ b/gnu/javax/sound/sampled/WAV/WAVReader.java
@@ -0,0 +1,236 @@
+/* WAVReader.java -- Read WAV files.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.sound.sampled.WAV;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.net.URL;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.UnsupportedAudioFileException;
+import javax.sound.sampled.spi.AudioFileReader;
+
+/**
+ * A WAV file reader.
+ *
+ * This code reads WAV files.
+ *
+ * There are many decent documents on the web describing the WAV file
+ * format. I didn't bother looking for the official document. If it
+ * exists, I'm not even sure if it is freely available. We should
+ * update this comment if we find out anything helpful here. I used
+ * http://www.sonicspot.com/guide/wavefiles.html
+ *
+ * @author Anthony Green (green@redhat.com)
+ *
+ */
+public class WAVReader extends AudioFileReader
+{
+ private static long readUnsignedIntLE (DataInputStream is)
+ throws IOException
+ {
+ byte[] buf = new byte[4];
+ is.readFully(buf);
+ return (buf[0] & 0xFF
+ | ((buf[1] & 0xFF) << 8)
+ | ((buf[2] & 0xFF) << 16)
+ | ((buf[3] & 0xFF) << 24));
+ }
+
+ private static short readUnsignedShortLE (DataInputStream is)
+ throws IOException
+ {
+ byte[] buf = new byte[2];
+ is.readFully(buf);
+ return (short) (buf[0] & 0xFF
+ | ((buf[1] & 0xFF) << 8));
+ }
+
+ /* Get an AudioFileFormat from the given File.
+ * @see javax.sound.sampled.spi.AudioFileReader#getAudioFileFormat(java.io.File)
+ */
+ public AudioFileFormat getAudioFileFormat(File file)
+ throws UnsupportedAudioFileException, IOException
+ {
+ InputStream is = new FileInputStream(file);
+ try
+ {
+ return getAudioFileFormat(is);
+ }
+ finally
+ {
+ is.close();
+ }
+ }
+
+ /* Get an AudioFileFormat from the given InputStream.
+ * @see javax.sound.sampled.spi.AudioFileReader#getAudioFileFormat(java.io.InputStream)
+ */
+ public AudioFileFormat getAudioFileFormat(InputStream in)
+ throws UnsupportedAudioFileException, IOException
+ {
+ DataInputStream din;
+
+ if (in instanceof DataInputStream)
+ din = (DataInputStream) in;
+ else
+ din = new DataInputStream(in);
+
+ if (din.readInt() != 0x52494646) // "RIFF"
+ throw new UnsupportedAudioFileException("Invalid WAV chunk header.");
+
+ // Read the length of this RIFF thing.
+ readUnsignedIntLE(din);
+
+ if (din.readInt() != 0x57415645) // "WAVE"
+ throw new UnsupportedAudioFileException("Invalid WAV chunk header.");
+
+ boolean foundFmt = false;
+ boolean foundData = false;
+
+ short compressionCode = 0, numberChannels = 0, blockAlign = 0, bitsPerSample = 0;
+ long sampleRate = 0, bytesPerSecond = 0;
+ long chunkLength = 0;
+
+ while (! foundData)
+ {
+ int chunkId = din.readInt();
+ chunkLength = readUnsignedIntLE(din);
+ switch (chunkId)
+ {
+ case 0x666D7420: // "fmt "
+ foundFmt = true;
+ compressionCode = readUnsignedShortLE(din);
+ numberChannels = readUnsignedShortLE(din);
+ sampleRate = readUnsignedIntLE(din);
+ bytesPerSecond = readUnsignedIntLE(din);
+ blockAlign = readUnsignedShortLE(din);
+ bitsPerSample = readUnsignedShortLE(din);
+ din.skip(chunkLength - 16);
+ break;
+ case 0x66616374: // "fact"
+ // FIXME: hold compression format dependent data.
+ din.skip(chunkLength);
+ break;
+ case 0x64617461: // "data"
+ if (! foundFmt)
+ throw new UnsupportedAudioFileException("This implementation requires WAV fmt chunks precede data chunks.");
+ foundData = true;
+ break;
+ default:
+ // Unrecognized chunk. Skip it.
+ din.skip(chunkLength);
+ }
+ }
+
+ AudioFormat.Encoding encoding;
+
+ switch (compressionCode)
+ {
+ case 1: // PCM/uncompressed
+ if (bitsPerSample <= 8)
+ encoding = AudioFormat.Encoding.PCM_UNSIGNED;
+ else
+ encoding = AudioFormat.Encoding.PCM_SIGNED;
+ break;
+
+ default:
+ throw new UnsupportedAudioFileException("Unrecognized WAV compression code: 0x"
+ + Integer.toHexString(compressionCode));
+ }
+
+ return new AudioFileFormat (AudioFileFormat.Type.WAVE,
+ new AudioFormat(encoding,
+ (float) sampleRate,
+ bitsPerSample,
+ numberChannels,
+ ((bitsPerSample + 7) / 8) * numberChannels,
+ (float) bytesPerSecond, false),
+ (int) chunkLength);
+ }
+
+ /* Get an AudioFileFormat from the given URL.
+ * @see javax.sound.sampled.spi.AudioFileReader#getAudioFileFormat(java.net.URL)
+ */
+ public AudioFileFormat getAudioFileFormat(URL url)
+ throws UnsupportedAudioFileException, IOException
+ {
+ InputStream is = url.openStream();
+ try
+ {
+ return getAudioFileFormat(is);
+ }
+ finally
+ {
+ is.close();
+ }
+ }
+
+ /* Get an AudioInputStream from the given File.
+ * @see javax.sound.sampled.spi.AudioFileReader#getAudioInputStream(java.io.File)
+ */
+ public AudioInputStream getAudioInputStream(File file)
+ throws UnsupportedAudioFileException, IOException
+ {
+ return getAudioInputStream(new FileInputStream(file));
+ }
+
+ /* Get an AudioInputStream from the given InputStream.
+ * @see javax.sound.sampled.spi.AudioFileReader#getAudioInputStream(java.io.InputStream)
+ */
+ public AudioInputStream getAudioInputStream(InputStream stream)
+ throws UnsupportedAudioFileException, IOException
+ {
+ AudioFileFormat aff = getAudioFileFormat(stream);
+ return new AudioInputStream(stream, aff.getFormat(), (long) aff.getFrameLength());
+ }
+
+ /* Get an AudioInputStream from the given URL.
+ * @see javax.sound.sampled.spi.AudioFileReader#getAudioInputStream(java.net.URL)
+ */
+ public AudioInputStream getAudioInputStream(URL url)
+ throws UnsupportedAudioFileException, IOException
+ {
+ return getAudioInputStream(url.openStream());
+ }
+}
diff --git a/gnu/javax/swing/text/html/parser/GnuParserDelegator.java b/gnu/javax/swing/text/html/parser/GnuParserDelegator.java
new file mode 100644
index 000000000..841db667e
--- /dev/null
+++ b/gnu/javax/swing/text/html/parser/GnuParserDelegator.java
@@ -0,0 +1,178 @@
+/* GnuParserDelegator.java -- The parser delegator which uses Swing DTD
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.swing.text.html.parser;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Serializable;
+
+import javax.swing.text.BadLocationException;
+import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.text.html.HTMLEditorKit.ParserCallback;
+import javax.swing.text.html.parser.DTD;
+import javax.swing.text.html.parser.ParserDelegator;
+import javax.swing.text.html.parser.TagElement;
+
+/**
+ * This parser delegator uses the different DTD ({@link HTML_401Swing}).
+ * It is derived from the ParserDelegator for the compatibility reasons.
+ *
+ * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
+ */
+public class GnuParserDelegator extends ParserDelegator implements Serializable
+{
+ class gnuParser
+ extends gnu.javax.swing.text.html.parser.support.Parser
+ {
+ private static final long serialVersionUID = 1;
+
+ gnuParser(DTD d)
+ {
+ super(d);
+ }
+
+ protected final void handleComment(char[] comment)
+ {
+ callBack.handleComment(comment, hTag.where.startPosition);
+ }
+
+ protected final void handleEmptyTag(TagElement tag)
+ throws javax.swing.text.ChangedCharSetException
+ {
+ callBack.handleSimpleTag(tag.getHTMLTag(), getAttributes(),
+ hTag.where.startPosition
+ );
+ }
+
+ protected final void handleEndTag(TagElement tag)
+ {
+ callBack.handleEndTag(tag.getHTMLTag(), hTag.where.startPosition);
+ }
+
+ protected final void handleError(int line, String message)
+ {
+ callBack.handleError(message, hTag.where.startPosition);
+ }
+
+ protected final void handleStartTag(TagElement tag)
+ {
+ htmlAttributeSet attributes = gnu.getAttributes();
+
+ if (tag.fictional())
+ attributes.addAttribute(ParserCallback.IMPLIED, Boolean.TRUE);
+
+ callBack.handleStartTag(tag.getHTMLTag(), attributes,
+ hTag.where.startPosition
+ );
+ }
+
+ protected final void handleText(char[] text)
+ {
+ callBack.handleText(text, hTag.where.startPosition);
+ }
+
+ DTD getDTD()
+ {
+ // Accessing the inherited gnu.javax.swing.text.html.parser.support.Parser
+ // field. super. is a workaround, required to support JDK1.3's javac.
+ return super.dtd;
+ }
+ }
+
+ /**
+ * Use serialVersionUID for interoperability.
+ */
+ private static final long serialVersionUID = -1276686502624777206L;
+
+ private DTD theDtd;
+
+ /**
+ * The callback.
+ * This is package-private to avoid an accessor method.
+ */
+ HTMLEditorKit.ParserCallback callBack;
+
+ /**
+ * The reference to the working class of HTML parser that is
+ * actually used to parse the document.
+ * This is package-private to avoid an accessor method.
+ */
+ gnuParser gnu;
+
+ /**
+ * Create the parser that uses the given DTD to parse the document.
+ *
+ * @param theDtd the DTD
+ */
+ public GnuParserDelegator(DTD theDtd)
+ {
+ this.theDtd = theDtd;
+ gnu = new gnuParser(theDtd);
+ }
+
+ /**
+ * Parses the HTML document, calling methods of the provided callback. This
+ * method must be multithread - safe.
+ *
+ * @param reader The reader to read the HTML document from
+ * @param a_callback The callback that is notifyed about the presence of HTML
+ * elements in the document.
+ * @param ignoreCharSet If thrue, any charset changes during parsing are
+ * ignored.
+ * @throws java.io.IOException
+ */
+ public void parse(Reader reader,
+ HTMLEditorKit.ParserCallback a_callback,
+ boolean ignoreCharSet) throws IOException
+ {
+ callBack = a_callback;
+ gnu.parse(reader);
+
+ callBack.handleEndOfLineString(gnu.getEndOfLineSequence());
+ try
+ {
+ callBack.flush();
+ }
+ catch (BadLocationException ex)
+ {
+ // Convert this into the supported type of exception.
+ throw new IOException(ex.getMessage());
+ }
+ }
+}
diff --git a/gnu/javax/swing/text/html/parser/HTML_401F.java b/gnu/javax/swing/text/html/parser/HTML_401F.java
index 1ed42a2ab..c3c347e36 100644
--- a/gnu/javax/swing/text/html/parser/HTML_401F.java
+++ b/gnu/javax/swing/text/html/parser/HTML_401F.java
@@ -759,23 +759,8 @@ public class HTML_401F
defElement(BODY, 0, true, true, null,
NONE
,
- new String[] {
- PCDATA, A, ABBR, ACRONYM,
- APPLET, B, BASEFONT, BDO, BIG,
- BR, BUTTON, CITE, CODE, DFN,
- EM, FONT, I, IFRAME, IMG,
- INPUT, KBD, LABEL, MAP, OBJECT,
- Q, S, SAMP, SCRIPT, SELECT,
- SMALL, SPAN, STRIKE, STRONG, SUB,
- SUP, TEXTAREA, TT, U, VAR,
- ADDRESS, BLOCKQUOTE, CENTER, DEL, DIR,
- DIV, DL, FIELDSET, FORM, H1,
- H2, H3, H4, H5, H6,
- HR, INS, ISINDEX, MENU, NOFRAMES,
- NOSCRIPT, OL, P, PRE, TABLE,
- UL
- }
- ,
+ getBodyElements()
+ ,
new AttributeList[] {
attr(sID, null, null, ID, IMPLIED),
attr(CLASS, null, null, 0, IMPLIED),
@@ -3634,7 +3619,7 @@ public class HTML_401F
* Crate a content model, consisting of the single
* element, specified by name.
*/
- private ContentModel model(String element)
+ protected ContentModel model(String element)
{
return new ContentModel(getElement(element));
}
@@ -3653,7 +3638,7 @@ public class HTML_401F
/**
* Create the model HEAD, BODY
- * @return
+ * @return the HTML content model of the whole document
*/
protected ContentModel createHtmlContentModel()
{
@@ -3725,5 +3710,27 @@ public class HTML_401F
li.type = ul.type = ol.type = '|';
return li;
}
-
+
+ /**
+ * Get elements that are allowed in the document body, at the zero level.
+ */
+ protected String[] getBodyElements()
+ {
+ return new String[] {
+ PCDATA, A, ABBR, ACRONYM,
+ APPLET, B, BASEFONT, BDO, BIG,
+ BR, BUTTON, CITE, CODE, DFN,
+ EM, FONT, I, IFRAME, IMG,
+ INPUT, KBD, LABEL, MAP, OBJECT,
+ Q, S, SAMP, SCRIPT, SELECT,
+ SMALL, SPAN, STRIKE, STRONG, SUB,
+ SUP, TEXTAREA, TT, U, VAR,
+ ADDRESS, BLOCKQUOTE, CENTER, DEL, DIR,
+ DIV, DL, FIELDSET, FORM, H1,
+ H2, H3, H4, H5, H6,
+ HR, INS, ISINDEX, MENU, NOFRAMES,
+ NOSCRIPT, OL, P, PRE, TABLE,
+ UL
+ };
+ }
}
diff --git a/gnu/javax/swing/text/html/parser/HTML_401Swing.java b/gnu/javax/swing/text/html/parser/HTML_401Swing.java
new file mode 100644
index 000000000..9c934f647
--- /dev/null
+++ b/gnu/javax/swing/text/html/parser/HTML_401Swing.java
@@ -0,0 +1,91 @@
+/* HTML_401Swing.java -- The HTML 4.01 DTD, adapted for HTML rendering in Swing
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.swing.text.html.parser;
+
+import javax.swing.text.html.parser.DTD;
+
+/**
+ * This class is necessary because the current implementation of the GNU
+ * Classpath Swing requires always enclose the text into paragraphs.
+ *
+ * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
+ */
+public class HTML_401Swing extends HTML_401F
+{
+ /**
+ * The singleton instance;
+ */
+ final static HTML_401Swing singleton = new HTML_401Swing();
+
+ /**
+ * Either takes the document (by name) from DTD table, or
+ * creates a new instance and registers it in the tabe.
+ * The document is registerd under name "-//W3C//DTD HTML 4.01 Frameset//EN".
+ * @return The new or existing DTD for parsing HTML 4.01 Frameset.
+ */
+ public static DTD getInstance()
+ {
+ return singleton;
+ }
+
+ /**
+ * Get elements that are allowed in the document body, at the zero level.
+ * This list disallows the text at this level (the implied P tag will be
+ * generated). It also disallows A, B, I, U, CITE and other similar
+ * elements that have the plain text inside. They will also be placed
+ * inside the generated implied P tags.
+ */
+ protected String[] getBodyElements()
+ {
+ return new String[] {
+ APPLET, BASEFONT,
+ BR, BUTTON,
+ IFRAME, IMG,
+ INPUT, LABEL, MAP, OBJECT,
+ SCRIPT, SELECT,
+ TEXTAREA,
+ BLOCKQUOTE, CENTER, DEL, DIR,
+ DIV, DL, FIELDSET, FORM, H1,
+ H2, H3, H4, H5, H6,
+ HR, INS, ISINDEX, MENU, NOFRAMES,
+ NOSCRIPT, OL, P, PRE, TABLE,
+ UL
+ };
+ }
+}
diff --git a/gnu/javax/swing/text/html/parser/htmlValidator.java b/gnu/javax/swing/text/html/parser/htmlValidator.java
index 1f9eee03a..4d287a677 100644
--- a/gnu/javax/swing/text/html/parser/htmlValidator.java
+++ b/gnu/javax/swing/text/html/parser/htmlValidator.java
@@ -233,7 +233,9 @@ public abstract class htmlValidator
Element fe = (Element) v;
// notify the content model that we add the proposed tag
- getCurrentContentModel().show(fe);
+ node ccm = getCurrentContentModel();
+ if (ccm != null)
+ ccm.show(fe);
openFictionalTag(fe);
Object vv = tagIsValidForContext(tElement);
@@ -301,13 +303,12 @@ public abstract class htmlValidator
}
/**
- * Check if this tag is valid for the current context.
- * Return Boolean.True if it is OK, Boolean.False
- * if it is surely not OK or the Element that the
- * content model recommends to insert making the situation
- * ok. If Boolean.True is returned, the content model current
- * position is moved forward. Otherwise this position remains
- * the same.
+ * Check if this tag is valid for the current context. Return Boolean.True if
+ * it is OK, Boolean.False if it is surely not OK or the Element that the
+ * content model recommends to insert making the situation ok. If Boolean.True
+ * is returned, the content model current position is moved forward. Otherwise
+ * this position remains the same.
+ *
* @param tElement
* @return
*/
@@ -321,7 +322,7 @@ public abstract class htmlValidator
// Check exclusions and inclusions.
ListIterator iter = stack.listIterator(stack.size());
- hTag t;
+ hTag t = null;
final int idx = tElement.getElement().index;
// Check only known tags.
@@ -331,19 +332,27 @@ public abstract class htmlValidator
while (iter.hasPrevious())
{
t = (hTag) iter.previous();
- if (!t.forcibly_closed)
+ if (! t.forcibly_closed)
{
- if (t.element.exclusions != null &&
- t.element.exclusions.get(idx)
- )
+ if (t.element.exclusions != null
+ && t.element.exclusions.get(idx))
return Boolean.FALSE;
if (t.element.inclusions != null)
inclusions.or(t.element.inclusions);
}
}
- if (!inclusions.get(idx))
- return Boolean.FALSE;
+ if (! inclusions.get(idx))
+ {
+ // If we need to insert something, and cannot do this, but
+ // it is allowed to insert the paragraph here, insert the
+ // paragraph.
+ Element P = dtd.getElement(HTML_401F.P);
+ if (inclusions.get(P.index))
+ return P;
+ else
+ return Boolean.FALSE;
+ }
}
return Boolean.TRUE;
}
diff --git a/gnu/xml/dom/DomIterator.java b/gnu/xml/dom/DomIterator.java
index 8a258926b..31f998246 100644
--- a/gnu/xml/dom/DomIterator.java
+++ b/gnu/xml/dom/DomIterator.java
@@ -253,7 +253,13 @@ public final class DomIterator
{
return here.getFirstChild();
}
-
+
+ // There's no way up or sideways from the root, so if we
+ // couldn't move down to a child, there's nowhere to go.
+ //
+ if (here == root)
+ return null;
+
//
// Siblings ... if forward, we visit them, if backwards
// we visit their children first.
diff --git a/gnu/xml/transform/ApplyTemplatesNode.java b/gnu/xml/transform/ApplyTemplatesNode.java
index 38b605a07..041809bdf 100644
--- a/gnu/xml/transform/ApplyTemplatesNode.java
+++ b/gnu/xml/transform/ApplyTemplatesNode.java
@@ -80,7 +80,7 @@ final class ApplyTemplatesNode
List sortKeys2 = new ArrayList(len);
for (int i = 0; i < len; i++)
sortKeys2.add(((Key) sortKeys.get(i)).clone(stylesheet));
- len = withParams.size();
+ len = withParams != null ? withParams.size() : 0;
List withParams2 = new ArrayList(len);
for (int i = 0; i < len; i++)
withParams2.add(((WithParam) withParams.get(i)).clone(stylesheet));
diff --git a/gnu/xml/transform/ForEachNode.java b/gnu/xml/transform/ForEachNode.java
index c8f51a6fe..25b824534 100644
--- a/gnu/xml/transform/ForEachNode.java
+++ b/gnu/xml/transform/ForEachNode.java
@@ -67,7 +67,7 @@ final class ForEachNode
TemplateNode clone(Stylesheet stylesheet)
{
- int len = sortKeys.size();
+ int len = sortKeys != null ? sortKeys.size() : 0;
List sortKeys2 = new ArrayList(len);
for (int i = 0; i < len; i++)
sortKeys2.add(((Key) sortKeys.get(i)).clone(stylesheet));
diff --git a/include/GtkDragSourceContextPeer.h b/include/GtkDragSourceContextPeer.h
new file mode 100644
index 000000000..87606ec1a
--- /dev/null
+++ b/include/GtkDragSourceContextPeer.h
@@ -0,0 +1,23 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+
+#ifndef __GtkDragSourceContextPeer__
+#define __GtkDragSourceContextPeer__
+
+#include <jni.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_nativeStartDrag (JNIEnv *env, jobject, jobject, jint, jint, jint, jstring);
+JNIEXPORT void JNICALL Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_connectSignals (JNIEnv *env, jobject, jobject);
+JNIEXPORT void JNICALL Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_create (JNIEnv *env, jobject, jobject);
+JNIEXPORT void JNICALL Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_nativeSetCursor (JNIEnv *env, jobject, jint) ;
+JNIEXPORT void JNICALL Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_setTarget (JNIEnv *env, jobject, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GtkDragSourceContextPeer__ */
diff --git a/include/Makefile.am b/include/Makefile.am
index cce6fd636..c36ff0687 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -47,7 +47,6 @@ $(top_srcdir)/include/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h \
$(top_srcdir)/include/gnu_java_awt_peer_gtk_GdkPixbufDecoder.h \
$(top_srcdir)/include/gnu_java_awt_peer_gtk_GdkRobotPeer.h \
$(top_srcdir)/include/gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice.h \
-$(top_srcdir)/include/gnu_java_awt_peer_gtk_GdkTextLayout.h \
$(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkButtonPeer.h \
$(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkCanvasPeer.h \
$(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkCheckboxMenuItemPeer.h \
@@ -76,7 +75,8 @@ $(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkTextFieldPeer.h \
$(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkToolkit.h \
$(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkWindowPeer.h \
$(top_srcdir)/include/gnu_java_awt_peer_gtk_GtkVolatileImage.h \
-$(top_srcdir)/include/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h
+$(top_srcdir)/include/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h \
+$(top_srcdir)/include/GtkDragSourceContextPeer.h
QTPEER_H_FILES = \
$(top_srcdir)/include/gnu_java_awt_peer_qt_QtCheckboxPeer.h \
diff --git a/include/gnu_java_awt_peer_gtk_CairoGraphics2D.h b/include/gnu_java_awt_peer_gtk_CairoGraphics2D.h
index 7f8138fe1..a54c7117e 100644
--- a/include/gnu_java_awt_peer_gtk_CairoGraphics2D.h
+++ b/include/gnu_java_awt_peer_gtk_CairoGraphics2D.h
@@ -16,6 +16,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_drawPixels (JN
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setGradient (JNIEnv *env, jobject, jlong, jdouble, jdouble, jdouble, jdouble, jint, jint, jint, jint, jint, jint, jint, jint, jboolean);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_setTexturePixels (JNIEnv *env, jobject, jlong, jintArray, jint, jint, jint);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetMatrix (JNIEnv *env, jobject, jlong, jdoubleArray);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoScale (JNIEnv *env, jobject, jlong, jdouble, jdouble);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetOperator (JNIEnv *env, jobject, jlong, jint);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetRGBAColor (JNIEnv *env, jobject, jlong, jdouble, jdouble, jdouble, jdouble);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetFillRule (JNIEnv *env, jobject, jlong, jint);
@@ -24,6 +25,9 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetDash (
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoDrawGlyphVector (JNIEnv *env, jobject, jlong, jobject, jfloat, jfloat, jint, jintArray, jfloatArray);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRelCurveTo (JNIEnv *env, jobject, jlong, jdouble, jdouble, jdouble, jdouble, jdouble, jdouble);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRectangle (JNIEnv *env, jobject, jlong, jdouble, jdouble, jdouble, jdouble);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoArc (JNIEnv *env, jobject, jlong, jdouble, jdouble, jdouble, jdouble, jdouble);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSave (JNIEnv *env, jobject, jlong);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRestore (JNIEnv *env, jobject, jlong);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoNewPath (JNIEnv *env, jobject, jlong);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoClosePath (JNIEnv *env, jobject, jlong);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoMoveTo (JNIEnv *env, jobject, jlong, jdouble, jdouble);
diff --git a/include/gnu_java_awt_peer_gtk_ComponentGraphics.h b/include/gnu_java_awt_peer_gtk_ComponentGraphics.h
index 2e1633452..0067119f6 100644
--- a/include/gnu_java_awt_peer_gtk_ComponentGraphics.h
+++ b/include/gnu_java_awt_peer_gtk_ComponentGraphics.h
@@ -15,6 +15,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_ComponentGraphics_disposeSurfa
JNIEXPORT jlong JNICALL Java_gnu_java_awt_peer_gtk_ComponentGraphics_initFromVolatile (JNIEnv *env, jobject, jlong, jint, jint);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_ComponentGraphics_start_1gdk_1drawing (JNIEnv *env, jobject);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_ComponentGraphics_end_1gdk_1drawing (JNIEnv *env, jobject);
+JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_ComponentGraphics_nativeGrab(JNIEnv *env, jclass, jobject );
JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_ComponentGraphics_hasXRender (JNIEnv *env, jclass);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_ComponentGraphics_copyAreaNative (JNIEnv *env, jobject, jobject, jint, jint, jint, jint, jint, jint);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_ComponentGraphics_drawVolatile (JNIEnv *env, jobject, jobject, jlong, jint, jint, jint, jint, jint, jint, jint, jint);
diff --git a/include/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h b/include/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h
index 2a619c609..6177a6fb9 100644
--- a/include/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h
+++ b/include/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h
@@ -16,6 +16,7 @@ JNIEXPORT jobjectArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment
JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_nativeGetDefaultScreenDevice (JNIEnv *env, jobject);
JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_nativeGetNumFontFamilies (JNIEnv *env, jobject);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_nativeGetFontFamilies (JNIEnv *env, jobject, jobjectArray);
+JNIEXPORT jintArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_getMouseCoordinates (JNIEnv *env, jobject);
#ifdef __cplusplus
}
diff --git a/include/gnu_java_awt_peer_gtk_GdkTextLayout.h b/include/gnu_java_awt_peer_gtk_GdkTextLayout.h
deleted file mode 100644
index fae4d775b..000000000
--- a/include/gnu_java_awt_peer_gtk_GdkTextLayout.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-
-#ifndef __gnu_java_awt_peer_gtk_GdkTextLayout__
-#define __gnu_java_awt_peer_gtk_GdkTextLayout__
-
-#include <jni.h>
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_setText (JNIEnv *env, jobject, jstring);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_setFont (JNIEnv *env, jobject, jobject);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_getExtents (JNIEnv *env, jobject, jdoubleArray, jdoubleArray);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_indexToPos (JNIEnv *env, jobject, jint, jdoubleArray);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_initState (JNIEnv *env, jobject);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_dispose (JNIEnv *env, jobject);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_cairoDrawGdkTextLayout (JNIEnv *env, jobject, jlong, jfloat, jfloat);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_initStaticState (JNIEnv *env, jclass);
-JNIEXPORT jobject JNICALL Java_gnu_java_awt_peer_gtk_GdkTextLayout_getOutline (JNIEnv *env, jobject, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __gnu_java_awt_peer_gtk_GdkTextLayout__ */
diff --git a/include/gnu_java_awt_peer_gtk_GtkChoicePeer.h b/include/gnu_java_awt_peer_gtk_GtkChoicePeer.h
index 1d92ed668..5450434d8 100644
--- a/include/gnu_java_awt_peer_gtk_GtkChoicePeer.h
+++ b/include/gnu_java_awt_peer_gtk_GtkChoicePeer.h
@@ -11,9 +11,8 @@ extern "C"
#endif
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_create (JNIEnv *env, jobject);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_append (JNIEnv *env, jobject, jobjectArray);
JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeGetSelected (JNIEnv *env, jobject);
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeAdd (JNIEnv *env, jobject, jstring, jint);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_add (JNIEnv *env, jobject, jstring, jint);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeRemove (JNIEnv *env, jobject, jint);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeRemoveAll (JNIEnv *env, jobject);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_connectSignals (JNIEnv *env, jobject);
diff --git a/include/gnu_java_awt_peer_gtk_GtkComponentPeer.h b/include/gnu_java_awt_peer_gtk_GtkComponentPeer.h
index f2014595f..f2b9ffe77 100644
--- a/include/gnu_java_awt_peer_gtk_GtkComponentPeer.h
+++ b/include/gnu_java_awt_peer_gtk_GtkComponentPeer.h
@@ -26,6 +26,8 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetS
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetParent (JNIEnv *env, jobject, jobject);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetRequestFocus (JNIEnv *env, jobject);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetDispatchKeyEvent (JNIEnv *env, jobject, jint, jlong, jint, jint, jint);
+JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetHasFocus (JNIEnv *env, jobject);
+JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetCanFocus (JNIEnv *env, jobject);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_realize (JNIEnv *env, jobject);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setNativeEventMask (JNIEnv *env, jobject);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkComponentPeer_connectSignals (JNIEnv *env, jobject);
diff --git a/include/gnu_java_awt_peer_gtk_GtkToolkit.h b/include/gnu_java_awt_peer_gtk_GtkToolkit.h
index ffeb39935..f1f5326cd 100644
--- a/include/gnu_java_awt_peer_gtk_GtkToolkit.h
+++ b/include/gnu_java_awt_peer_gtk_GtkToolkit.h
@@ -17,6 +17,8 @@ JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_getScreenResolution
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_sync (JNIEnv *env, jobject);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_loadSystemColors (JNIEnv *env, jobject, jintArray);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkMain (JNIEnv *env, jclass);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkQuit (JNIEnv *env, jclass);
+JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_getMouseNumberOfButtons (JNIEnv *env, jobject);
#ifdef __cplusplus
}
diff --git a/include/gnu_java_awt_peer_gtk_GtkWindowPeer.h b/include/gnu_java_awt_peer_gtk_GtkWindowPeer.h
index ad447f16a..c9a629a82 100644
--- a/include/gnu_java_awt_peer_gtk_GtkWindowPeer.h
+++ b/include/gnu_java_awt_peer_gtk_GtkWindowPeer.h
@@ -13,6 +13,8 @@ extern "C"
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetTitle (JNIEnv *env, jobject, jstring);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetResizable (JNIEnv *env, jobject, jboolean);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetModal (JNIEnv *env, jobject, jboolean);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetAlwaysOnTop (JNIEnv *env, jobject, jboolean);
+JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowHasFocus (JNIEnv *env, jobject);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_realize (JNIEnv *env, jobject);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_create (JNIEnv *env, jobject, jint, jboolean, jobject);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisibleNative (JNIEnv *env, jobject, jboolean);
diff --git a/include/gnu_java_net_local_LocalSocketImpl.h b/include/gnu_java_net_local_LocalSocketImpl.h
index 3309053f1..b1f1fcd84 100644
--- a/include/gnu_java_net_local_LocalSocketImpl.h
+++ b/include/gnu_java_net_local_LocalSocketImpl.h
@@ -13,7 +13,7 @@ extern "C"
JNIEXPORT void JNICALL Java_gnu_java_net_local_LocalSocketImpl_create (JNIEnv *env, jobject, jboolean);
JNIEXPORT void JNICALL Java_gnu_java_net_local_LocalSocketImpl_listen (JNIEnv *env, jobject, jint);
JNIEXPORT void JNICALL Java_gnu_java_net_local_LocalSocketImpl_accept (JNIEnv *env, jobject, jobject);
-JNIEXPORT jint JNICALL Java_gnu_java_net_local_LocalSocketImpl_available (JNIEnv *env, jobject);
+JNIEXPORT jint JNICALL Java_gnu_java_net_local_LocalSocketImpl_available (JNIEnv *env, jobject, jint);
JNIEXPORT void JNICALL Java_gnu_java_net_local_LocalSocketImpl_close (JNIEnv *env, jobject);
JNIEXPORT void JNICALL Java_gnu_java_net_local_LocalSocketImpl_sendUrgentData (JNIEnv *env, jobject, jint);
JNIEXPORT void JNICALL Java_gnu_java_net_local_LocalSocketImpl_shutdownInput (JNIEnv *env, jobject);
@@ -21,8 +21,8 @@ JNIEXPORT void JNICALL Java_gnu_java_net_local_LocalSocketImpl_shutdownOutput (J
JNIEXPORT void JNICALL Java_gnu_java_net_local_LocalSocketImpl_unlink (JNIEnv *env, jobject);
JNIEXPORT void JNICALL Java_gnu_java_net_local_LocalSocketImpl_localBind (JNIEnv *env, jobject, jobject);
JNIEXPORT void JNICALL Java_gnu_java_net_local_LocalSocketImpl_localConnect (JNIEnv *env, jobject, jobject);
-JNIEXPORT jint JNICALL Java_gnu_java_net_local_LocalSocketImpl_read (JNIEnv *env, jobject, jbyteArray, jint, jint);
-JNIEXPORT void JNICALL Java_gnu_java_net_local_LocalSocketImpl_write (JNIEnv *env, jobject, jbyteArray, jint, jint);
+JNIEXPORT jint JNICALL Java_gnu_java_net_local_LocalSocketImpl_read (JNIEnv *env, jobject, jint, jbyteArray, jint, jint);
+JNIEXPORT void JNICALL Java_gnu_java_net_local_LocalSocketImpl_write (JNIEnv *env, jobject, jint, jbyteArray, jint, jint);
#ifdef __cplusplus
}
diff --git a/include/java_lang_VMSystem.h b/include/java_lang_VMSystem.h
index 11b89ba27..1bc55cf9d 100644
--- a/include/java_lang_VMSystem.h
+++ b/include/java_lang_VMSystem.h
@@ -15,7 +15,7 @@ JNIEXPORT jint JNICALL Java_java_lang_VMSystem_identityHashCode (JNIEnv *env, jc
JNIEXPORT void JNICALL Java_java_lang_VMSystem_setIn (JNIEnv *env, jclass, jobject);
JNIEXPORT void JNICALL Java_java_lang_VMSystem_setOut (JNIEnv *env, jclass, jobject);
JNIEXPORT void JNICALL Java_java_lang_VMSystem_setErr (JNIEnv *env, jclass, jobject);
-JNIEXPORT jlong JNICALL Java_java_lang_VMSystem_currentTimeMillis (JNIEnv *env, jclass);
+JNIEXPORT jlong JNICALL Java_java_lang_VMSystem_nanoTime (JNIEnv *env, jclass);
JNIEXPORT jobject JNICALL Java_java_lang_VMSystem_environ (JNIEnv *env, jclass);
JNIEXPORT jstring JNICALL Java_java_lang_VMSystem_getenv (JNIEnv *env, jclass, jstring);
diff --git a/include/jvmti.h b/include/jvmti.h
new file mode 100644
index 000000000..23419f920
--- /dev/null
+++ b/include/jvmti.h
@@ -0,0 +1,1815 @@
+/* jvmti.h - Java Virtual Machine Tool Interface
+ 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. */
+
+
+/* Note: this file must be compilable by the C compiler (for now,
+ assuming GNU C is ok). This means you must never use `//'
+ comments, and all C++-specific code must be conditional on
+ __cplusplus. */
+
+#ifndef _CLASSPATH_JVMTI_H
+#define _CLASSPATH_JVMTI_H
+#include <jni.h>
+
+/* The VM might define JVMTI base types */
+#ifndef _CLASSPATH_VM_JVMTI_TYPES_DEFINED
+
+typedef jobject jthread;
+typedef jobject jthreadGroup;
+typedef jlong jlocation;
+typedef struct _Jv_rawMonitorID *jrawMonitorID;
+
+#endif /* !_CLASSPATH_VM_JVMTI_TYPES_DEFINED */
+
+/* JVMTI Version */
+#define JVMTI_VERSION_1_0 0x30010000
+#define JVMTI_VERSION (JVMTI_VERSION_1_0 + 38) /* Spec version is 1.0.38 */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* These functions might be defined in libraries which we load; the
+ JVMTI implementation calls them at the appropriate times. */
+extern JNIEXPORT jint JNICALL Agent_OnLoad (JavaVM *vm, char *options,
+ void *reserved);
+extern JNIEXPORT void JNICALL Agent_OnUnload (JavaVM *vm);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Forward declarations */
+typedef struct _jvmtiAddrLocationMap jvmtiAddrLocationMap;
+#ifdef __cplusplus
+typedef struct _Jv_JVMTIEnv jvmtiEnv;
+#else
+typedef const struct _Jv_jvmtiEnv jvmtiEnv;
+#endif
+
+/*
+ * Error constants
+ */
+
+typedef enum
+{
+ /* Universal Errors */
+ JVMTI_ERROR_NONE = 0,
+ JVMTI_ERROR_NULL_POINTER = 100,
+ JVMTI_ERROR_OUT_OF_MEMORY = 110,
+ JVMTI_ERROR_ACCESS_DENIED = 111,
+ JVMTI_ERROR_WRONG_PHASE = 112,
+ JVMTI_ERROR_INTERNAL = 113,
+ JVMTI_ERROR_UNATTACHED_THREAD = 115,
+ JVMTI_ERROR_INVALID_ENVIRONMENT = 116,
+
+ /* Function-specific Required Errors */
+ JVMTI_ERROR_INVALID_PRIORITY = 12,
+ JVMTI_ERROR_THREAD_NOT_SUSPENDED = 13,
+ JVMTI_ERROR_THREAD_SUSPENDED = 14,
+ JVMTI_ERROR_THREAD_NOT_ALIVE = 15,
+ JVMTI_ERROR_CLASS_NOT_PREPARED = 22,
+ JVMTI_ERROR_NO_MORE_FRAMES = 31,
+ JVMTI_ERROR_OPAQUE_FRAME = 32,
+ JVMTI_ERROR_DUPLICATE = 40,
+ JVMTI_ERROR_NOT_FOUND = 41,
+ JVMTI_ERROR_NOT_MONITOR_OWNER = 51,
+ JVMTI_ERROR_INTERRUPT = 52,
+ JVMTI_ERROR_UNMODIFIABLE_CLASS = 79,
+ JVMTI_ERROR_NOT_AVAILABLE = 98,
+ JVMTI_ERROR_ABSENT_INFORMATION = 101,
+ JVMTI_ERROR_INVALID_EVENT_TYPE = 102,
+ JVMTI_ERROR_NATIVE_METHOD = 104,
+
+ /* Function-specific Agent Errors */
+ JVMTI_ERROR_INVALID_THREAD = 10,
+ JVMTI_ERROR_INVALID_THREAD_GROUP = 11,
+ JVMTI_ERROR_INVALID_OBJECT = 20,
+ JVMTI_ERROR_INVALID_CLASS = 21,
+ JVMTI_ERROR_INVALID_METHODID = 23,
+ JVMTI_ERROR_INVALID_LOCATION = 24,
+ JVMTI_ERROR_INVALID_FIELDID = 25,
+ JVMTI_ERROR_TYPE_MISMATCH = 34,
+ JVMTI_ERROR_INVALID_SLOT = 35,
+ JVMTI_ERROR_INVALID_MONITOR = 50,
+ JVMTI_ERROR_INVALID_CLASS_FORMAT = 60,
+ JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION = 61,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED = 63,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED = 64,
+ JVMTI_ERROR_INVALID_TYPESTATE = 65,
+ JVMTI_ERROR_FAILS_VERIFICATION = 62,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED = 66,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED = 67,
+ JVMTI_ERROR_UNSUPPORTED_VERSION = 68,
+ JVMTI_ERROR_NAMES_DONT_MATCH = 69,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED = 70,
+ JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED = 71,
+ JVMTI_ERROR_MUST_POSSESS_CAPABILITY = 99,
+ JVMTI_ERROR_ILLEGAL_ARGUMENT = 103,
+} jvmtiError;
+
+/*
+ * Enumeration Definitions
+ */
+
+typedef enum
+{
+ JVMTI_DISABLE = 0,
+ JVMTI_ENABLE = 1
+} jvmtiEventMode;
+
+typedef enum
+{
+ JVMTI_HEAP_OBJECT_TAGGED = 1,
+ JVMTI_HEAP_OBJECT_UNTAGGED = 2,
+ JVMTI_HEAP_OBJECT_EITHER = 3
+} jvmtiHeapObjectFilter;
+
+typedef enum
+{
+ JVMTI_HEAP_ROOT_JNI_GLOBAL = 1,
+ JVMTI_HEAP_ROOT_SYSTEM_CLASS = 2,
+ JVMTI_HEAP_ROOT_MONITOR = 3,
+ JVMTI_HEAP_ROOT_STACK_LOCAL = 4,
+ JVMTI_HEAP_ROOT_JNI_LOCAL = 5,
+ JVMTI_HEAP_ROOT_THREAD = 6,
+ JVMTI_HEAP_ROOT_OTHER = 7
+} jvmtiHeapRootKind;
+
+typedef enum
+{
+ JVMTI_ITERATION_ABORT = 0,
+ JVMTI_ITERATION_CONTINUE = 1,
+ JVMTI_ITERATION_IGNORE = 2
+} jvmtiIterationControl;
+
+typedef enum
+{
+ JVMTI_JLOCATION_OTHER = 0,
+ JVMTI_JLOCATION_JVMBCI = 1,
+ JVMTI_JLOCATION_MACHINEPC = 2
+} jvmtiJlocationFormat;
+
+typedef enum
+{
+ JVMTI_REFERENCE_CLASS = 1,
+ JVMTI_REFERENCE_FIELD = 2,
+ JVMTI_REFERENCE_ARRAY_ELEMENT = 3,
+ JVMTI_REFERENCE_CLASS_LOADER = 4,
+ JVMTI_REFERENCE_SIGNERS = 5,
+ JVMTI_REFERENCE_PROTECTION_DOMAIN = 6,
+ JVMTI_REFERENCE_INTERFACE = 7,
+ JVMTI_REFERENCE_STATIC_FIELD = 8,
+ JVMTI_REFERENCE_CONSTANT_POOL = 9
+} jvmtiObjectReferenceKind;
+
+typedef enum
+{
+ JVMTI_KIND_IN = 91,
+ JVMTI_KIND_IN_PTR = 92,
+ JVMTI_KIND_IN_BUF = 93,
+ JVMTI_KIND_ALLOC_BUF = 94,
+ JVMTI_KIND_ALLOC_ALLOC_BUF = 95,
+ JVMTI_KIND_OUT = 96,
+ JVMTI_KIND_OUT_BUF = 97
+} jvmtiParamKind;
+
+typedef enum
+{
+ JVMTI_TYPE_JBYTE = 101,
+ JVMTI_TYPE_JCHAR = 102,
+ JVMTI_TYPE_JSHORT = 103,
+ JVMTI_TYPE_JINT = 104,
+ JVMTI_TYPE_JLONG = 105,
+ JVMTI_TYPE_JFLOAT = 106,
+ JVMTI_TYPE_JDOUBLE = 107,
+ JVMTI_TYPE_JBOOLEAN = 108,
+ JVMTI_TYPE_JOBJECT = 109,
+ JVMTI_TYPE_JTHREAD = 110,
+ JVMTI_TYPE_JCLASS = 111,
+ JVMTI_TYPE_JVALUE = 112,
+ JVMTI_TYPE_JFIELDID = 113,
+ JVMTI_TYPE_JMETHODID = 114,
+ JVMTI_TYPE_CCHAR = 115,
+ JVMTI_TYPE_CVOID = 116,
+ JVMTI_TYPE_JNIENV = 117
+} jvmtiParamTypes;
+
+typedef enum
+{
+ JVMTI_PHASE_ONLOAD = 1,
+ JVMTI_PHASE_PRIMORDIAL = 2,
+ JVMTI_PHASE_LIVE = 4,
+ JVMTI_PHASE_START = 6,
+ JVMTI_PHASE_DEAD = 8
+} jvmtiPhase;
+
+typedef enum
+{
+ JVMTI_TIMER_USER_CPU = 30,
+ JVMTI_TIMER_TOTAL_CPU = 31,
+ JVMTI_TIMER_ELAPSED = 32
+} jvmtiTimerKind;
+
+typedef enum
+{
+ JVMTI_VERBOSE_OTHER = 0,
+ JVMTI_VERBOSE_GC = 1,
+ JVMTI_VERBOSE_CLASS = 2,
+ JVMTI_VERBOSE_JNI = 4
+} jvmtiVerboseFlag;
+
+/* Version information */
+#define JVMTI_VERSION_INTERFACE_JNI 0x00000000
+#define JVMTI_VERSION_INTERFACE_JVMTI 0x30000000
+#define JVMTI_VERSION_MASK_INTERFACE_TYPE 0x70000000
+#define JVMTI_VERSION_MASK_MAJOR 0x0FFF0000
+#define JVMTI_VERSION_MASK_MINOR 0x0000FF00
+#define JVMTI_VERSION_MASK_MICRO 0x000000FF
+#define JVMTI_VERSION_SHIFT_MAJOR 16
+#define JVMTI_VERSION_SHIFT_MINOR 8
+#define JVMTI_VERSION_SHIFT_MICRO 0
+
+/*
+ * Events and event callbacks
+ */
+
+typedef enum
+{
+ JVMTI_EVENT_VM_INIT = 50,
+ JVMTI_EVENT_VM_DEATH = 51,
+ JVMTI_EVENT_THREAD_START = 52,
+ JVMTI_EVENT_THREAD_END = 53,
+ JVMTI_EVENT_CLASS_FILE_LOAD_HOOK = 54,
+ JVMTI_EVENT_CLASS_LOAD = 55,
+ JVMTI_EVENT_CLASS_PREPARE = 56,
+ JVMTI_EVENT_VM_START = 57,
+ JVMTI_EVENT_EXCEPTION = 58,
+ JVMTI_EVENT_EXCEPTION_CATCH = 59,
+ JVMTI_EVENT_SINGLE_STEP = 60,
+ JVMTI_EVENT_FRAME_POP = 61,
+ JVMTI_EVENT_BERAKPOINT = 62,
+ JVMTI_EVENT_FIELD_ACCESS = 63,
+ JVMTI_EVENT_FIELD_MODIFICATION = 64,
+ JVMTI_EVENT_METHOD_ENTRY = 65,
+ JVMTI_EVENT_METHOD_EXIT = 66,
+ JVMTI_EVENT_NATIVE_METHOD_BIND = 67,
+ JVMTI_EVENT_COMPILED_METHOD_LOAD = 68,
+ JVMTI_EVENT_COMPILED_METHOD_UNLOAD = 69,
+ JVMTI_EVENT_DYNAMIC_CODE_GENERATED = 70,
+ JVMTI_EVENT_DATA_DUMP_REQUEST = 71,
+ JVMTI_EVENT_MONITOR_WAIT = 73,
+ JVMTI_EVENT_MONITOR_WAITED = 74,
+ JVMTI_EVENT_MONITOR_CONTENDED_ENTER = 75,
+ JVMTI_EVENT_MONITOR_CONTENDED_ENTERED = 76,
+ JVMTI_EVENT_GARBAGE_COLLECTION_START = 81,
+ JVMTI_EVENT_GARBAGE_COLLECTION_FINISH = 82,
+ JVMTI_EVENT_OBJECT_FREE = 83,
+ JVMTI_EVENT_VM_OBJECT_ALLOC = 84
+} jvmtiEvent;
+
+typedef void *jvmtiEventReserved;
+
+typedef void (JNICALL *jvmtiEventSingleStep)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jmethodID method,
+ jlocation location);
+
+typedef void (JNICALL *jvmtiEventBreakpoint)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jmethodID method,
+ jlocation location);
+
+typedef void (JNICALL *jvmtiEventFieldAccess)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jmethodID method,
+ jlocation location, jclass field_klass, jobject object, jfieldID field);
+
+typedef void (JNICALL *jvmtiEventFieldModification)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jmethodID method,
+ jlocation location, jclass field_klass, jobject object, jfieldID field,
+ char signature_type, jvalue new_value);
+
+typedef void (JNICALL *jvmtiEventFramePop)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jmethodID method,
+ jboolean was_popped_by_exception);
+
+typedef void (JNICALL *jvmtiEventMethodEntry)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jmethodID method);
+
+typedef void (JNICALL *jvmtiEventMethodExit)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jmethodID method,
+ jboolean was_popped_by_exception, jvalue return_value);
+
+typedef void (JNICALL *jvmtiEventNativeMethodBind)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jmethodID method,
+ void *address, void **new_address_ptr);
+
+typedef void (JNICALL *jvmtiEventException)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jmethodID method,
+ jlocation location, jobject exception, jmethodID catch_method,
+ jlocation catch_location);
+
+typedef void (JNICALL *jvmtiEventExceptionCatch)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jmethodID method,
+ jlocation location, jobject exception);
+
+typedef void (JNICALL *jvmtiEventThreadStart)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread);
+
+typedef void (JNICALL *jvmtiEventThreadEnd)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread);
+
+typedef void (JNICALL *jvmtiEventClassLoad)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jclass klass);
+
+typedef void (JNICALL *jvmtiEventClassPrepare)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thraed, jclass klass);
+
+typedef void (JNICALL *jvmtiEventClassFileLoadHook)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jclass class_being_redefined,
+ jobject loader, const char *name, jobject protection_domain,
+ jint class_data_len, const unsigned char *class_data,
+ jint *new_class_data_len, unsigned char **new_class_data);
+
+typedef void (JNICALL *jvmtiEventVMStart)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env);
+
+typedef void (JNICALL *jvmtiEventVMInit)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread);
+
+typedef void (JNICALL *jvmtiEventVMDeath)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env);
+
+typedef void (JNICALL *jvmtiEventCompiledMethodLoad)
+ (jvmtiEnv *jvmti_env, jmethodID method, jint code_size,
+ const void *code_addr, jint map_length, const jvmtiAddrLocationMap *map,
+ const void *compile_info);
+
+typedef void (JNICALL *jvmtiEventCompiledMethodUnload)
+ (jvmtiEnv *jvmti_env, jmethodID method, const void *code_addr);
+
+typedef void (JNICALL *jvmtiEventDynamicCodeGenerated)
+ (jvmtiEnv *jvmti_env, const char *name, const void *address, jint length);
+
+typedef void (JNICALL *jvmtiEventDataDumpRequest)
+ (jvmtiEnv *jvmti_env);
+
+typedef void (JNICALL *jvmtiEventMonitorContendedEnter)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jobject object);
+
+typedef void (JNICALL *jvmtiEventMonitorContendedEntered)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jobject object);
+
+typedef void (JNICALL *jvmtiEventMonitorWait)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jobject object,
+ jlong timeout);
+
+typedef void (JNICALL *jvmtiEventMonitorWaited)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jobject object,
+ jboolean timed_out);
+
+typedef void (JNICALL *jvmtiEventVMObjectAlloc)
+ (jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jobject object,
+ jclass object_klass, jlong size);
+
+typedef void (JNICALL *jvmtiEventObjectFree)
+ (jvmtiEnv *jvmti_env, jlong tag);
+
+typedef void (JNICALL *jvmtiEventGarbageCollectionStart)
+ (jvmtiEnv *jvmti_env);
+
+typedef void (JNICALL *jvmtiEventGarbageCollectionFinish)
+ (jvmtiEnv *jvmti_env);
+
+typedef struct
+{
+ jvmtiEventVMInit VMInit;
+ jvmtiEventVMDeath VMDeath;
+ jvmtiEventThreadStart ThreadStart;
+ jvmtiEventThreadEnd ThreadEnd;
+ jvmtiEventClassFileLoadHook ClassFileLoadHook;
+ jvmtiEventClassLoad ClassLoad;
+ jvmtiEventClassPrepare ClassPrepare;
+ jvmtiEventVMStart VMStart;
+ jvmtiEventException Exception;
+ jvmtiEventExceptionCatch ExceptionCatch;
+ jvmtiEventSingleStep SingleStep;
+ jvmtiEventFramePop FramePop;
+ jvmtiEventBreakpoint Breakpoint;
+ jvmtiEventFieldAccess FieldAccess;
+ jvmtiEventFieldModification FieldModification;
+ jvmtiEventMethodEntry MethodEntry;
+ jvmtiEventMethodExit MethodExit;
+ jvmtiEventNativeMethodBind NativeMethodBind;
+ jvmtiEventCompiledMethodLoad CompiledMethodLoad;
+ jvmtiEventCompiledMethodUnload CompiledMethodUnload;
+ jvmtiEventDynamicCodeGenerated DynamicCodeGenerated;
+ jvmtiEventDataDumpRequest DataDumpRequest;
+ jvmtiEventReserved reserved72;
+ jvmtiEventMonitorWait MonitorWait;
+ jvmtiEventMonitorWaited MonitorWaited;
+ jvmtiEventMonitorContendedEnter MonitorContendedEnter;
+ jvmtiEventMonitorContendedEntered MonitorContendedEntered;
+ jvmtiEventReserved reserved77;
+ jvmtiEventReserved reserved78;
+ jvmtiEventReserved reserved79;
+ jvmtiEventReserved reserved80;
+ jvmtiEventGarbageCollectionStart GarbageCollectionStart;
+ jvmtiEventGarbageCollectionFinish GarbageCollectionFinish;
+ jvmtiEventObjectFree ObjectFree;
+ jvmtiEventVMObjectAlloc VMObjectAlloc;
+} jvmtiEventCallbacks;
+
+/*
+ * Function and Structure Type Definitions
+ */
+
+struct _jvmtiAddrLocationMap
+{
+ const void *start_address;
+ jlocation location;
+};
+
+typedef struct
+{
+ unsigned int can_tag_objects : 1;
+ unsigned int can_generate_field_modification_events : 1;
+ unsigned int can_generate_field_access_events : 1;
+ unsigned int can_get_bytecodes : 1;
+ unsigned int can_get_synthetic_attribute : 1;
+ unsigned int can_get_owned_monitor_info : 1;
+ unsigned int can_get_current_contended_monitor : 1;
+ unsigned int can_get_monitor_info : 1;
+ unsigned int can_pop_frame : 1;
+ unsigned int can_redefine_classes : 1;
+ unsigned int can_signal_thread : 1;
+ unsigned int can_get_source_file_name : 1;
+ unsigned int can_get_line_numbers : 1;
+ unsigned int can_get_source_debug_extension : 1;
+ unsigned int can_access_local_variables : 1;
+ unsigned int can_maintain_original_method_order : 1;
+ unsigned int can_generate_single_step_events : 1;
+ unsigned int can_generate_exception_events : 1;
+ unsigned int can_generate_frame_pop_events : 1;
+ unsigned int can_generate_breakpoint_events : 1;
+ unsigned int can_suspend : 1;
+ unsigned int can_redefine_any_class : 1;
+ unsigned int can_get_current_thread_cpu_time : 1;
+ unsigned int can_get_thread_cpu_time : 1;
+ unsigned int can_generate_method_entry_events : 1;
+ unsigned int can_generate_method_exit_events : 1;
+ unsigned int can_generate_all_class_hook_events : 1;
+ unsigned int can_generate_compiled_method_load_events : 1;
+ unsigned int can_generate_monitor_events : 1;
+ unsigned int can_generate_vm_object_alloc_events : 1;
+ unsigned int can_generate_native_method_bind_events : 1;
+ unsigned int can_generate_garbage_collection_events : 1;
+ unsigned int can_generate_object_free_events : 1;
+ unsigned int : 15;
+ unsigned int : 16;
+ unsigned int : 16;
+ unsigned int : 16;
+ unsigned int : 16;
+ unsigned int : 16;
+} jvmtiCapabilities;
+
+typedef struct
+{
+ jclass klass;
+ jint class_byte_count;
+ const unsigned char *class_bytes;
+} jvmtiClassDefinition;
+
+typedef struct
+{
+ char *name;
+ jvmtiParamKind kind;
+ jvmtiParamTypes base_type;
+ jboolean null_ok;
+} jvmtiParamInfo;
+
+typedef struct
+{
+ jint extension_event_index;
+ char *id;
+ char *short_description;
+ jint param_count;
+ jvmtiParamInfo* params;
+} jvmtiExtensionEventInfo;
+
+typedef jvmtiError (JNICALL *jvmtiExtensionFunction)
+ (jvmtiEnv *jvmti_enf, ...);
+
+typedef struct
+{
+ jvmtiExtensionFunction func;
+ char *id;
+ char *short_description;
+ jint param_count;
+ jvmtiParamInfo *params;
+ jint error_count;
+ jvmtiError *errors;
+} jvmtiExtensionFunctionInfo;
+
+typedef struct
+{
+ jmethodID method;
+ jlocation location;
+} jvmtiFrameInfo;
+
+typedef struct
+{
+ jlocation start_location;
+ jint line_number;
+} jvmtiLineNumberEntry;
+
+typedef struct
+{
+ jlocation start_location;
+ jint length;
+ char *name;
+ char *signature;
+ char *generic_signature;
+ jint slot;
+} jvmtiLocalVariableEntry;
+
+typedef struct
+{
+ jthread owner;
+ jint entry_count;
+ jint waiter_count;
+ jthread *waiters;
+ jint notify_waiter_count;
+ jthread *notify_waiters;
+} jvmtiMonitorUsage;
+
+typedef struct
+{
+ jthread thread;
+ jint state;
+ jvmtiFrameInfo *frame_buffer;
+ jint frame_count;
+} jvmtiStackInfo;
+
+typedef struct
+{
+ jthreadGroup parent;
+ char *name;
+ jint max_priority;
+ jboolean is_daemon;
+} jvmtiThreadGroupInfo;
+
+typedef struct
+{
+ char *name;
+ jint priority;
+ jboolean is_daemon;
+ jthreadGroup thread_group;
+ jobject context_class_loader;
+} jvmtiThreadInfo;
+
+typedef struct
+{
+ jlong max_value;
+ jboolean may_skip_forward;
+ jboolean may_skip_backward;
+ jvmtiTimerKind kind;
+ jlong reserved1;
+ jlong reserved2;
+} jvmtiTimerInfo;
+
+typedef void (JNICALL *jvmtiExtensionEvent)
+ (jvmtiEnv *jvmti_env, ...);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiHeapObjectCallback)
+ (jlong class_tag, jlong size, jlong *tag_ptr, void *user_data);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiHeapRootCallback)
+ (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong *tag_ptr,
+ void *user_data);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiObjectReferenceCallback)
+ (jvmtiObjectReferenceKind reference_kind, jlong class_tag, jlong size,
+ jlong *tag_ptr, jlong referrer_tag, jint referrer_index, void *user_data);
+
+typedef jvmtiIterationControl (JNICALL *jvmtiStackReferenceCallback)
+ (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong *tag_ptr,
+ jlong thread_tag, jint depth, jmethodID method, jint slot, void *user_data);
+
+typedef void (JNICALL *jvmtiStartFunction)
+ (jvmtiEnv *env, JNIEnv *jni_env, void *arg);
+
+/*
+ * JVM Tool Interface Base Types
+ */
+typedef struct JNINativeInterface jniNativeInterface;
+
+struct _Jv_jvmtiEnv
+{
+ void *reserved1;
+
+ jvmtiError (JNICALL *SetEventNotificationMode) (jvmtiEnv *env,
+ jvmtiEventMode mode,
+ jvmtiEvent event_type,
+ jthread event_thread, ...);
+ void *reserved3;
+
+ jvmtiError (JNICALL *GetAllThreads) (jvmtiEnv *env,
+ jint *threads_count_ptr,
+ jthread **threads_ptr);
+
+ jvmtiError (JNICALL *SuspendThread) (jvmtiEnv *env,
+ jthread thread);
+
+ jvmtiError (JNICALL *ResumeThread) (jvmtiEnv *env,
+ jthread thread);
+
+ jvmtiError (JNICALL *StopThread) (jvmtiEnv *env,
+ jthread thread);
+
+ jvmtiError (JNICALL *InterruptThread) (jvmtiEnv *env,
+ jthread thread);
+
+ jvmtiError (JNICALL *GetThreadInfo) (jvmtiEnv *env,
+ jthread thread,
+ jvmtiThreadInfo *info_ptr);
+
+ jvmtiError (JNICALL *GetOwnedMonitorInfo) (jvmtiEnv *env,
+ jthread thread,
+ jint *owned_monitor_count_ptr,
+ jobject **owned_monitors_ptr);
+
+ jvmtiError (JNICALL *GetCurrentContendedMonitor) (jvmtiEnv *env,
+ jthread thread,
+ jobject *monitor_ptr);
+
+ jvmtiError (JNICALL *RunAgentThread) (jvmtiEnv *env,
+ jthread thread,
+ jvmtiStartFunction proc,
+ const void *arg,
+ jint priority);
+
+ jvmtiError (JNICALL *GetTopThreadGroups) (jvmtiEnv *env,
+ jint *group_count_ptr,
+ jthreadGroup **groups_ptr);
+
+ jvmtiError (JNICALL *GetThreadGroupInfo) (jvmtiEnv *env,
+ jthreadGroup group,
+ jvmtiThreadGroupInfo *info_ptr);
+
+ jvmtiError (JNICALL *GetThreadGroupChildren) (jvmtiEnv *env,
+ jthreadGroup group,
+ jint *thread_count_ptr,
+ jthread **threads_ptr,
+ jint *group_count_ptr,
+ jthreadGroup **groups_ptr);
+ jvmtiError (JNICALL *GetFrameCount) (jvmtiEnv *env,
+ jthread thread,
+ jint *count_ptr);
+
+ jvmtiError (JNICALL *GetThreadState) (jvmtiEnv *env,
+ jthread thread,
+ jint *thread_state_ptr);
+
+ void *reserved18;
+
+ jvmtiError (JNICALL *GetFrameLocation) (jvmtiEnv *env,
+ jthread thread,
+ jint depth,
+ jmethodID *method_ptr,
+ jlocation *location_ptr);
+
+ jvmtiError (JNICALL *NotifyPopFrame) (jvmtiEnv *env,
+ jthread thread,
+ jint depth);
+
+ jvmtiError (JNICALL *GetLocalObject) (jvmtiEnv *env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jobject *value_ptr);
+
+ jvmtiError (JNICALL *GetLocalInt) (jvmtiEnv *env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jint *value_ptr);
+
+ jvmtiError (JNICALL *GetLocalLong) (jvmtiEnv *env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jlong *value_ptr);
+
+ jvmtiError (JNICALL *GetLocalFloat) (jvmtiEnv *env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jfloat *value_ptr);
+
+ jvmtiError (JNICALL *GetLocalDouble) (jvmtiEnv *env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jdouble *value_ptr);
+
+ jvmtiError (JNICALL *SetLocalObject) (jvmtiEnv *env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jobject value);
+
+ jvmtiError (JNICALL *SetLocalInt) (jvmtiEnv *env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jint value);
+
+ jvmtiError (JNICALL *SetLocalLong) (jvmtiEnv *env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jlong value);
+
+ jvmtiError (JNICALL *SetLocalFloat) (jvmtiEnv *env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jfloat value);
+
+ jvmtiError (JNICALL *SetLocalDouble) (jvmtiEnv *env,
+ jthread thread,
+ jint depth,
+ jint slot,
+ jdouble value);
+
+ jvmtiError (JNICALL *CreateRawMonitor) (jvmtiEnv *env,
+ const char *name,
+ jrawMonitorID *monitor_ptr);
+
+ jvmtiError (JNICALL *DestroyRawMonitor) (jvmtiEnv *env,
+ jrawMonitorID monitor);
+
+ jvmtiError (JNICALL *RawMonitorEnter) (jvmtiEnv *env,
+ jrawMonitorID monitor);
+
+ jvmtiError (JNICALL *RawMonitorExit) (jvmtiEnv *env,
+ jrawMonitorID monitor);
+
+ jvmtiError (JNICALL *RawMonitorWait) (jvmtiEnv *env,
+ jrawMonitorID monitor);
+
+ jvmtiError (JNICALL *RawMonitorNotify) (jvmtiEnv *env,
+ jrawMonitorID monitor);
+
+ jvmtiError (JNICALL *RawMonitorNotifyAll) (jvmtiEnv *env,
+ jrawMonitorID monitor);
+
+ jvmtiError (JNICALL *SetBreakpoint) (jvmtiEnv *env,
+ jmethodID method,
+ jlocation location);
+
+ jvmtiError (JNICALL *ClearBreakpoint) (jvmtiEnv *env,
+ jmethodID method,
+ jlocation location);
+
+ void *reserved40;
+
+ jvmtiError (JNICALL *SetFieldAccessWatch) (jvmtiEnv *env,
+ jclass klass,
+ jfieldID field);
+
+ jvmtiError (JNICALL *ClearFieldAccessWatch) (jvmtiEnv *env,
+ jclass klass,
+ jfieldID field);
+
+ jvmtiError (JNICALL *SetFieldModificationWatch) (jvmtiEnv *env,
+ jclass klass,
+ jfieldID field);
+
+ jvmtiError (JNICALL *ClearFieldModificationWatch) (jvmtiEnv *env,
+ jclass klass,
+ jfieldID field);
+
+ void *reserved45;
+
+ jvmtiError (JNICALL *Allocate) (jvmtiEnv *env,
+ jlong size,
+ unsigned char **mem_ptr);
+
+ jvmtiError (JNICALL *Deallocate) (jvmtiEnv *env,
+ unsigned char *mem);
+
+ jvmtiError (JNICALL *GetClassSignature) (jvmtiEnv *env,
+ jclass klass,
+ char **signature_ptr,
+ char **generic_ptr);
+
+ jvmtiError (JNICALL *GetClassStatus) (jvmtiEnv *env,
+ jclass klass,
+ jint *status_ptr);
+
+ jvmtiError (JNICALL *GetSourceFileName) (jvmtiEnv *env,
+ jclass klass,
+ char *source_name_ptr);
+
+ jvmtiError (JNICALL *GetClassModifiers) (jvmtiEnv *env,
+ jclass klass,
+ jint *modifiers_ptr);
+
+ jvmtiError (JNICALL *GetClassMethods) (jvmtiEnv *env,
+ jclass klass,
+ jint *method_count_ptr,
+ jmethodID **methods_ptr);
+
+ jvmtiError (JNICALL *GetClassFields) (jvmtiEnv *env,
+ jclass klass,
+ jint *field_count_ptr,
+ jfieldID **fields_ptr);
+
+ jvmtiError (JNICALL *GetImplementedInterfaces) (jvmtiEnv *env,
+ jclass klass,
+ jint *interface_count_ptr,
+ jclass **interfaces_ptr);
+
+ jvmtiError (JNICALL *IsInterface) (jvmtiEnv *env,
+ jclass klass,
+ jboolean *is_interface_ptr);
+
+ jvmtiError (JNICALL *IsArrayClass) (jvmtiEnv *env,
+ jclass klass,
+ jboolean *is_array_class_ptr);
+
+ jvmtiError (JNICALL *GetClassLoader) (jvmtiEnv *env,
+ jclass klass,
+ jobject *classloader_ptr);
+
+ jvmtiError (JNICALL *GetObjectHashCode) (jvmtiEnv *env,
+ jobject object,
+ jint *hash_code_ptr);
+
+ jvmtiError (JNICALL *GetObjectMonitorUsage) (jvmtiEnv *env,
+ jobject object,
+ jvmtiMonitorUsage *info_ptr);
+
+ jvmtiError (JNICALL *GetFieldName) (jvmtiEnv *env,
+ jclass klass,
+ jfieldID field,
+ char **name_ptr,
+ char **signature_ptr,
+ char **generic_ptr);
+
+ jvmtiError (JNICALL *GetFieldDeclaringClass) (jvmtiEnv *env,
+ jclass klass,
+ jfieldID field,
+ jclass *declaring_class_ptr);
+
+ jvmtiError (JNICALL *GetFieldModifiers) (jvmtiEnv *env,
+ jclass klass,
+ jfieldID field,
+ jint *modifiers_ptr);
+
+ jvmtiError (JNICALL *IsFieldSynthetic) (jvmtiEnv *env,
+ jclass klass,
+ jfieldID field,
+ jboolean *is_synthetic_ptr);
+
+ jvmtiError (JNICALL *GetMethodName) (jvmtiEnv *env,
+ jmethodID method,
+ char **name_ptr,
+ char **signature_ptr,
+ char **generic_ptr);
+
+ jvmtiError (JNICALL *GetMethodDeclaringClass) (jvmtiEnv *env,
+ jmethodID method,
+ jclass *declaring_class_ptr);
+
+
+ jvmtiError (JNICALL *GetMethodModifiers) (jvmtiEnv *env,
+ jmethodID method,
+ jint *modifiers_ptr);
+
+ void *reserved67;
+
+ jvmtiError (JNICALL *GetMaxLocals) (jvmtiEnv *env,
+ jmethodID method,
+ jint *max_ptr);
+
+ jvmtiError (JNICALL *GetArgumentsSize) (jvmtiEnv *env,
+ jmethodID method,
+ jint *size_ptr);
+
+ jvmtiError (JNICALL *GetLineNumberTable) (jvmtiEnv *env,
+ jmethodID method,
+ jint *entry_count_ptr,
+ jvmtiLineNumberEntry **table_ptr);
+
+ jvmtiError (JNICALL *GetMethodLocation) (jvmtiEnv *env,
+ jmethodID method,
+ jlocation *start_location_ptr,
+ jlocation *end_location_ptr);
+
+ jvmtiError (JNICALL *GetLocalVariableTable) (jvmtiEnv *env,
+ jmethodID method,
+ jint *entry_count_ptr,
+ jvmtiLocalVariableEntry **table_ptr);
+
+ void *reserved73;
+
+ void *reserved74;
+
+ jvmtiError (JNICALL *GetBytecodes) (jvmtiEnv *env,
+ jmethodID method,
+ jint *bytecode_count_ptr,
+ unsigned char **bytecodes_ptr);
+
+ jvmtiError (JNICALL *IsMethodNative) (jvmtiEnv *env,
+ jmethodID method,
+ jboolean *is_native_ptr);
+
+ jvmtiError (JNICALL *IsMethodSynthetic) (jvmtiEnv *env,
+ jmethodID method,
+ jboolean *is_synthetic_ptr);
+
+ jvmtiError (JNICALL *GetLoadedClasses) (jvmtiEnv *env,
+ jint *class_count_ptr,
+ jclass **classes_ptr);
+
+ jvmtiError (JNICALL *GetClassLoaderClasses) (jvmtiEnv *env,
+ jobject initiating_loader,
+ jint *class_count_ptr,
+ jclass **classes_ptr);
+
+ jvmtiError (JNICALL *PopFrame) (jvmtiEnv *env,
+ jthread thread);
+
+ void *reserved81;
+
+ void *reserved82;
+
+ void *reserved83;
+
+ void *reserved84;
+
+ void *reserved85;
+
+ void *reserved86;
+
+ jvmtiError (JNICALL *RedefineClasses) (jvmtiEnv *env,
+ jint class_count,
+ const jvmtiClassDefinition* class_definitions);
+
+ jvmtiError (JNICALL *GetVersionNumber) (jvmtiEnv *env,
+ jint *version_ptr);
+
+ jvmtiError (JNICALL *GetCapabilities) (jvmtiEnv *env,
+ jvmtiCapabilities *capabilities_ptr);
+
+ jvmtiError (JNICALL *GetSourceDebugExtension) (jvmtiEnv *env,
+ jclass klass,
+ char **source_debug_extension_ptr);
+
+ jvmtiError (JNICALL *IsMethodObsolete) (jvmtiEnv *env,
+ jmethodID method,
+ jboolean *is_obsolete_ptr);
+
+ jvmtiError (JNICALL *SuspendThreadList) (jvmtiEnv *env,
+ jint request_count,
+ const jthread *request_list,
+ jvmtiError *results);
+
+ jvmtiError (JNICALL *ResumeThreadList) (jvmtiEnv *env,
+ jint request_count,
+ const jthread *request_list,
+ jvmtiError *results);
+
+ void *reserved94;
+
+ void *reserved95;
+
+ void *reserved96;
+
+ void *reserved97;
+
+ void *reserved98;
+
+ void *reserved99;
+
+ jvmtiError (JNICALL *GetAllStackTraces) (jvmtiEnv *env,
+ jint max_frame_count,
+ jvmtiStackInfo **stack_info_ptr,
+ jint *thread_count_ptr);
+
+ jvmtiError (JNICALL *GetThreadListStackTraces) (jvmtiEnv *env,
+ jint thread_count,
+ const jthread *thread_list,
+ jint max_frame_count,
+ jvmtiStackInfo **stack_info_ptr);
+
+ jvmtiError (JNICALL *GetThreadLocalStorage) (jvmtiEnv *env,
+ jthread thread,
+ void **data_ptr);
+
+ jvmtiError (JNICALL *SetThreadLocalStorage) (jvmtiEnv *env,
+ jthread thread,
+ const void *data);
+
+ jvmtiError (JNICALL *GetStackTrace) (jvmtiEnv *env,
+ jthread thread,
+ jint start_depth,
+ jint max_frame_count,
+ jvmtiFrameInfo *frame_buffer,
+ jint *count_ptr);
+
+ void *reserved105;
+
+ jvmtiError (JNICALL *GetTag) (jvmtiEnv *env,
+ jobject object,
+ jlong *tag_ptr);
+
+ jvmtiError (JNICALL *SetTag) (jvmtiEnv *env,
+ jobject object,
+ jlong tag);
+
+ jvmtiError (JNICALL *ForceGarbageCollection) (jvmtiEnv *env);
+
+ jvmtiError (JNICALL *IterateOverObjectsReachableFromObject) (jvmtiEnv *env,
+ jobject object,
+ jvmtiObjectReferenceCallback object_reference_callback,
+ void *user_data);
+
+ jvmtiError (JNICALL *IterateOverReachableObjects) (jvmtiEnv *env,
+ jvmtiHeapRootCallback heap_root_callback,
+ jvmtiStackReferenceCallback stack_ref_callback,
+ jvmtiObjectReferenceCallback object_ref_callback,
+ void *user_data);
+
+ jvmtiError (JNICALL *IterateOverHeap) (jvmtiEnv *env,
+ jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ void *user_data);
+
+ jvmtiError (JNICALL *IterateOverInstanceOfClass) (jvmtiEnv *env,
+ jclass klass,
+ jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ void *user_data);
+
+ void *reserved113;
+
+ jvmtiError (JNICALL *GetObjectsWithTags) (jvmtiEnv *env,
+ jint tag_count,
+ const jlong *tags,
+ jint *count_ptr,
+ jobject **object_result_ptr,
+ jlong **tag_result_ptr);
+
+ void *reserved115;
+
+ void *reserved116;
+
+ void *reserved117;
+
+ void *reserved118;
+
+ void *reserved119;
+
+ jvmtiError (JNICALL *SetJNIFunctionTable) (jvmtiEnv *env,
+ const jniNativeInterface *function_table);
+
+ jvmtiError (JNICALL *GetJNIFunctionTable) (jvmtiEnv *env,
+ jniNativeInterface **function_table_ptr);
+
+ jvmtiError (JNICALL *SetEventCallbacks) (jvmtiEnv *env,
+ const jvmtiEventCallbacks *callbacks,
+ jint size_of_callbacks);
+
+ jvmtiError (JNICALL *GenerateEvents) (jvmtiEnv *env,
+ jvmtiEvent event_type);
+
+ jvmtiError (JNICALL *GetExtensionFunctions) (jvmtiEnv *env,
+ jint *extension_count_ptr,
+ jvmtiExtensionFunctionInfo **extensions);
+
+ jvmtiError (JNICALL *GetExtensionEvents) (jvmtiEnv *env,
+ jint *extension_count_ptr,
+ jvmtiExtensionEventInfo **extensions);
+
+ jvmtiError (JNICALL *SetExtensionEventCallback) (jvmtiEnv *env,
+ jint extension_event_index,
+ jvmtiExtensionEvent callback);
+
+ jvmtiError (JNICALL *DisposeEnvironment) (jvmtiEnv *env);
+
+ jvmtiError (JNICALL *GetErrorName) (jvmtiEnv *env,
+ jvmtiError error,
+ char **name_ptr);
+
+ jvmtiError (JNICALL *GetJLocationFormat) (jvmtiEnv *env,
+ jvmtiJlocationFormat *format_ptr);
+
+ jvmtiError (JNICALL *GetSystemProperties) (jvmtiEnv *env,
+ jint *count_ptr,
+ char ***property_ptr);
+
+ jvmtiError (JNICALL *GetSystemProperty) (jvmtiEnv *env,
+ const char *property,
+ char **value_ptr);
+
+ jvmtiError (JNICALL *SetSystemProperty) (jvmtiEnv *env,
+ const char *property,
+ const char *value);
+
+ jvmtiError (JNICALL *GetPhase) (jvmtiEnv *env,
+ jvmtiPhase *phase_ptr);
+
+ jvmtiError (JNICALL *GetCurrentThreadCpuTimerInfo) (jvmtiEnv *env,
+ jvmtiTimerInfo *info_ptr);
+
+ jvmtiError (JNICALL *GetCurrentThreadCpuTime) (jvmtiEnv *env,
+ jlong *nanos_ptr);
+
+ jvmtiError (JNICALL *GetThreadCpuTimerInfo) (jvmtiEnv *env,
+ jvmtiTimerInfo *info_ptr);
+
+ jvmtiError (JNICALL *GetThreadCpuTime) (jvmtiEnv *env,
+ jthread thread,
+ jlong *nanos_ptr);
+
+ jvmtiError (JNICALL *GetTimerInfo) (jvmtiEnv *env,
+ jvmtiTimerInfo *info_ptr);
+
+ jvmtiError (JNICALL *GetTime) (jvmtiEnv *env,
+ jlong *nanos_ptr);
+
+ jvmtiError (JNICALL *GetPotentialCapabilities) (jvmtiEnv *env,
+ jvmtiCapabilities *capabilities_ptr);
+
+ void *reserved141;
+
+ jvmtiError (JNICALL *AddCapabilities) (jvmtiEnv *env,
+ const jvmtiCapabilities *capabilities_ptr);
+
+ jvmtiError (JNICALL *RelinquishCapabilities) (jvmtiEnv *env,
+ const jvmtiCapabilities *capabilities_ptr);
+
+ jvmtiError (JNICALL *GetAvailableProcessors) (jvmtiEnv *env,
+ jint *processor_count_ptr);
+
+ void *reserved145;
+
+ void *reserved146;
+
+ jvmtiError (JNICALL *GetEnvironmentLocalStorage) (jvmtiEnv *env,
+ void **data_ptr);
+
+ jvmtiError (JNICALL *SetEnvironmentLocalStorage) (jvmtiEnv *env,
+ const void *data);
+
+ jvmtiError (JNICALL *AddToBootstrapClassLoaderSearch) (jvmtiEnv *env,
+ const char *segment);
+
+ jvmtiError (JNICALL *SetVerboseFlag) (jvmtiEnv *env,
+ jvmtiVerboseFlag flag,
+ jboolean value);
+
+ void *reserved151;
+
+ void *reserved152;
+
+ void *reserved153;
+
+ jvmtiError (JNICALL *GetObjectSize) (jvmtiEnv *env,
+ jobject object,
+ jlong *size_ptr);
+};
+
+#ifdef __cplusplus
+class _Jv_JVMTIEnv
+{
+ public:
+ /* Method table */
+ struct _Jv_jvmtiEnv *p;
+
+#ifdef _CLASSPATH_JVMTIENV_CONTENTS
+ _CLASSPATH_JVMTIENV_CONTENTS
+#endif
+
+ jvmtiError SetEventNotificationMode (jvmtiEventMode mode,
+ jvmtiEvent event_type,
+ jthread event_thread, ...)
+ {
+ va_list args;
+ va_start (args, event_thread);
+ jvmtiError result = p->SetEventNotificationMode (this, mode, event_type,
+ event_thread, args);
+ va_end (args);
+ return result;
+ }
+
+ jvmtiError GetAllThreads (jint *threads_count_ptr, jthread **threads_ptr)
+ { return p->GetAllThreads (this, threads_count_ptr, threads_ptr); }
+
+ jvmtiError SuspendThread (jthread thread)
+ { return p->SuspendThread (this, thread); }
+
+ jvmtiError ResumeThread (jthread thread)
+ { return p->ResumeThread (this, thread); }
+
+ jvmtiError StopThread (jthread thread)
+ { return p->StopThread (this, thread); }
+
+ jvmtiError InterruptThread (jthread thread)
+ { return p->InterruptThread (this, thread); }
+
+ jvmtiError GetThreadInfo (jthread thread, jvmtiThreadInfo *info_ptr)
+ { return p->GetThreadInfo (this, thread, info_ptr); }
+
+ jvmtiError GetOwnedMonitorInfo (jthread thread,
+ jint *owned_monitor_count_ptr,
+ jobject **owned_monitors_ptr)
+ {
+ return p->GetOwnedMonitorInfo (this, thread, owned_monitor_count_ptr,
+ owned_monitors_ptr);
+ }
+
+ jvmtiError GetCurrentContendedMonitor (jthread thread, jobject *monitor_ptr)
+ { return p->GetCurrentContendedMonitor (this, thread, monitor_ptr); }
+
+ jvmtiError RunAgentThread (jthread thread, jvmtiStartFunction proc,
+ const void *arg, jint priority)
+ { return p->RunAgentThread (this, thread, proc, arg, priority); }
+
+ jvmtiError GetTopThreadGroups (jint *group_count_ptr,
+ jthreadGroup **groups_ptr)
+ { return p->GetTopThreadGroups (this, group_count_ptr, groups_ptr); }
+
+ jvmtiError GetThreadGroupInfo (jthreadGroup group,
+ jvmtiThreadGroupInfo *info_ptr)
+ { return p->GetThreadGroupInfo (this, group, info_ptr); }
+
+ jvmtiError GetThreadGroupChildren (jthreadGroup group,
+ jint *thread_count_ptr,
+ jthread **threads_ptr,
+ jint *group_count_ptr,
+ jthreadGroup **groups_ptr)
+ {
+ return p->GetThreadGroupChildren (this, group, thread_count_ptr,
+ threads_ptr, group_count_ptr,
+ groups_ptr);
+ }
+
+ jvmtiError GetFrameCount (jthread thread, jint *count_ptr)
+ { return p->GetFrameCount (this, thread, count_ptr); }
+
+ jvmtiError GetThreadState (jthread thread, jint *thread_state_ptr)
+ { return p->GetThreadState (this, thread, thread_state_ptr); }
+
+ jvmtiError GetFrameLocation (jthread thread, jint depth,
+ jmethodID *method_ptr, jlocation *location_ptr)
+ {
+ return p->GetFrameLocation (this, thread, depth, method_ptr,
+ location_ptr);
+ }
+
+ jvmtiError NotifyPopFrame (jthread thread, jint depth)
+ { return p->NotifyPopFrame (this, thread, depth); }
+
+ jvmtiError GetLocalObject (jthread thread, jint depth, jint slot,
+ jobject *value_ptr)
+ { return p->GetLocalObject (this, thread, depth, slot, value_ptr); }
+
+ jvmtiError GetLocalInt (jthread thread, jint depth, jint slot,
+ jint *value_ptr)
+ { return p->GetLocalInt (this, thread, depth, slot, value_ptr); }
+
+ jvmtiError GetLocalLong (jthread thread, jint depth, jint slot,
+ jlong *value_ptr)
+ { return p->GetLocalLong (this, thread, depth, slot, value_ptr); }
+
+ jvmtiError GetLocalFloat (jthread thread, jint depth, jint slot,
+ jfloat *value_ptr)
+ { return p->GetLocalFloat (this, thread, depth, slot, value_ptr); }
+
+ jvmtiError GetLocalDouble (jthread thread, jint depth, jint slot,
+ jdouble *value_ptr)
+ { return p->GetLocalDouble (this, thread, depth, slot, value_ptr); }
+
+ jvmtiError SetLocalObject (jthread thread, jint depth, jint slot,
+ jobject value)
+ { return p->SetLocalObject (this, thread, depth, slot, value); }
+
+ jvmtiError SetLocalInt (jthread thread, jint depth, jint slot,
+ jint value)
+ { return p->SetLocalInt (this, thread, depth, slot, value); }
+
+ jvmtiError SetLocalLong (jthread thread, jint depth, jint slot,
+ jlong value)
+ { return p->SetLocalLong (this, thread, depth, slot, value); }
+
+ jvmtiError SetLocalFloat (jthread thread, jint depth, jint slot,
+ jfloat value)
+ { return p->SetLocalFloat (this, thread, depth, slot, value); }
+
+ jvmtiError SetLocalDouble (jthread thread, jint depth, jint slot,
+ jdouble value)
+ { return p->SetLocalDouble (this, thread, depth, slot, value); }
+
+ jvmtiError CreateRawMonitor (const char *name, jrawMonitorID *monitor_ptr)
+ { return p->CreateRawMonitor (this, name, monitor_ptr); }
+
+ jvmtiError DestroyRawMonitor (jrawMonitorID monitor)
+ { return p->DestroyRawMonitor (this, monitor); }
+
+ jvmtiError RawMonitorEnter (jrawMonitorID monitor)
+ { return p->RawMonitorEnter (this, monitor); }
+
+ jvmtiError RawMonitorExit (jrawMonitorID monitor)
+ { return p->RawMonitorExit (this, monitor); }
+
+ jvmtiError RawMonitorWait (jrawMonitorID monitor)
+ { return p->RawMonitorWait (this, monitor); }
+
+ jvmtiError RawMonitorNotify (jrawMonitorID monitor)
+ { return p->RawMonitorNotify (this, monitor); }
+
+ jvmtiError RawMonitorNotifyAll (jrawMonitorID monitor)
+ { return p->RawMonitorNotifyAll (this, monitor); }
+
+ jvmtiError SetBreakpoint (jmethodID method, jlocation location)
+ { return p->SetBreakpoint (this, method, location); }
+
+ jvmtiError ClearBreakpoint (jmethodID method, jlocation location)
+ { return p->ClearBreakpoint (this, method, location); }
+
+ jvmtiError SetFieldAccessWatch (jclass klass, jfieldID field)
+ { return p->SetFieldAccessWatch (this, klass, field); }
+
+ jvmtiError ClearFieldAccessWatch (jclass klass, jfieldID field)
+ { return p->ClearFieldAccessWatch (this, klass, field); }
+
+ jvmtiError SetFieldModificationWatch (jclass klass, jfieldID field)
+ { return p->SetFieldModificationWatch (this, klass, field); }
+
+ jvmtiError ClearFieldModificationWatch (jclass klass, jfieldID field)
+ { return p->ClearFieldModificationWatch (this, klass, field); }
+
+ jvmtiError Allocate (jlong size, unsigned char **mem_ptr)
+ { return p->Allocate (this, size, mem_ptr); }
+
+ jvmtiError Deallocate (unsigned char *mem)
+ { return p->Deallocate (this, mem); }
+
+ jvmtiError GetClassSignature (jclass klass, char **signature_ptr,
+ char **generic_ptr)
+ { return p->GetClassSignature (this, klass, signature_ptr, generic_ptr); }
+
+ jvmtiError GetClassStatus (jclass klass, jint *status_ptr)
+ { return p->GetClassStatus (this, klass, status_ptr); }
+
+ jvmtiError GetSourceFileName (jclass klass, char *source_name_ptr)
+ { return p->GetSourceFileName (this, klass, source_name_ptr); }
+
+ jvmtiError GetClassModifiers (jclass klass, jint *modifiers_ptr)
+ { return p->GetClassModifiers (this, klass, modifiers_ptr); }
+
+ jvmtiError GetClassMethods (jclass klass, jint *method_count_ptr,
+ jmethodID **methods_ptr)
+ { return p->GetClassMethods (this, klass, method_count_ptr, methods_ptr); }
+
+ jvmtiError GetClassFields (jclass klass, jint *field_count_ptr,
+ jfieldID **fields_ptr)
+ { return p->GetClassFields (this, klass, field_count_ptr, fields_ptr); }
+
+ jvmtiError GetImplementedInterfaces (jclass klass,
+ jint *interface_count_ptr,
+ jclass **interfaces_ptr)
+ {
+ return p->GetImplementedInterfaces (this, klass, interface_count_ptr,
+ interfaces_ptr);
+ }
+
+ jvmtiError IsInterface (jclass klass, jboolean *is_interface_ptr)
+ { return p->IsInterface (this, klass, is_interface_ptr); }
+
+ jvmtiError IsArrayClass (jclass klass, jboolean *is_array_class_ptr)
+ { return p->IsArrayClass (this, klass, is_array_class_ptr); }
+
+ jvmtiError GetClassLoader (jclass klass, jobject *classloader_ptr)
+ { return p->GetClassLoader (this, klass, classloader_ptr); }
+
+ jvmtiError GetObjectHashCode (jobject object, jint *hash_code_ptr)
+ { return p->GetObjectHashCode (this, object, hash_code_ptr); }
+
+ jvmtiError GetObjectMonitorUsage (jobject object,
+ jvmtiMonitorUsage *info_ptr)
+ { return p->GetObjectMonitorUsage (this, object, info_ptr); }
+
+ jvmtiError GetFieldName (jclass klass, jfieldID field, char **name_ptr,
+ char **signature_ptr, char **generic_ptr)
+ {
+ return p->GetFieldName (this, klass, field, name_ptr,
+ signature_ptr, generic_ptr);
+ }
+
+ jvmtiError GetFieldDeclaringClass (jclass klass, jfieldID field,
+ jclass *declaring_class_ptr)
+ {
+ return p->GetFieldDeclaringClass (this, klass, field,
+ declaring_class_ptr);
+ }
+
+ jvmtiError GetFieldModifiers (jclass klass, jfieldID field,
+ jint *modifiers_ptr)
+ { return p->GetFieldModifiers (this, klass, field, modifiers_ptr); }
+
+ jvmtiError IsFieldSynthetic (jclass klass, jfieldID field,
+ jboolean *is_synthetic_ptr)
+ { return p->IsFieldSynthetic (this, klass, field, is_synthetic_ptr); }
+
+ jvmtiError GetMethodName (jmethodID method, char **name_ptr,
+ char **signature_ptr, char **generic_ptr)
+ {
+ return p->GetMethodName (this, method, name_ptr, signature_ptr,
+ generic_ptr);
+ }
+
+ jvmtiError GetMethodDeclaringClass (jmethodID method,
+ jclass *declaring_class_ptr)
+ { return p->GetMethodDeclaringClass (this, method, declaring_class_ptr); }
+
+
+ jvmtiError GetMethodModifiers (jmethodID method, jint *modifiers_ptr)
+ { return p->GetMethodModifiers (this, method, modifiers_ptr); }
+
+ jvmtiError GetMaxLocals (jmethodID method, jint *max_ptr)
+ { return p->GetMaxLocals (this, method, max_ptr); }
+
+ jvmtiError GetArgumentsSize (jmethodID method, jint *size_ptr)
+ { return p->GetArgumentsSize (this, method, size_ptr); }
+
+ jvmtiError GetLineNumberTable (jmethodID method, jint *entry_count_ptr,
+ jvmtiLineNumberEntry **table_ptr)
+ { return p->GetLineNumberTable (this, method, entry_count_ptr, table_ptr); }
+
+ jvmtiError GetMethodLocation (jmethodID method,
+ jlocation *start_location_ptr,
+ jlocation *end_location_ptr)
+ {
+ return p->GetMethodLocation (this, method, start_location_ptr,
+ end_location_ptr);
+ }
+
+ jvmtiError GetLocalVariableTable (jmethodID method, jint *entry_count_ptr,
+ jvmtiLocalVariableEntry **table_ptr)
+ {
+ return p->GetLocalVariableTable (this, method, entry_count_ptr,
+ table_ptr);
+ }
+
+ jvmtiError GetBytecodes (jmethodID method, jint *bytecode_count_ptr,
+ unsigned char **bytecodes_ptr)
+ {
+ return p->GetBytecodes (this, method, bytecode_count_ptr,
+ bytecodes_ptr);
+ }
+
+ jvmtiError IsMethodNative (jmethodID method, jboolean *is_native_ptr)
+ { return p->IsMethodNative (this, method, is_native_ptr); }
+
+ jvmtiError IsMethodSynthetic (jmethodID method, jboolean *is_synthetic_ptr)
+ { return p->IsMethodSynthetic (this, method, is_synthetic_ptr); }
+
+ jvmtiError GetLoadedClasses (jint *class_count_ptr, jclass **classes_ptr)
+ { return p->GetLoadedClasses (this, class_count_ptr, classes_ptr); }
+
+ jvmtiError GetClassLoaderClasses (jobject initiating_loader,
+ jint *class_count_ptr,
+ jclass **classes_ptr)
+ {
+ return p->GetClassLoaderClasses (this, initiating_loader,
+ class_count_ptr, classes_ptr);
+ }
+
+ jvmtiError PopFrame (jthread thread)
+ { return p->PopFrame (this, thread); }
+
+ jvmtiError RedefineClasses (jint class_count,
+ const jvmtiClassDefinition* class_definitions)
+ { return p->RedefineClasses (this, class_count, class_definitions); }
+
+ jvmtiError GetVersionNumber (jint *version_ptr)
+ { return p->GetVersionNumber (this, version_ptr); }
+
+ jvmtiError GetCapabilities (jvmtiCapabilities *capabilities_ptr)
+ { return p->GetCapabilities (this, capabilities_ptr); }
+
+ jvmtiError GetSourceDebugExtension (jclass klass,
+ char **source_debug_extension_ptr)
+ {
+ return p->GetSourceDebugExtension (this, klass,
+ source_debug_extension_ptr);
+ }
+
+ jvmtiError IsMethodObsolete (jmethodID method, jboolean *is_obsolete_ptr)
+ { return p->IsMethodObsolete (this, method, is_obsolete_ptr); }
+
+
+ jvmtiError SuspendThreadList (jint request_count,
+ const jthread *request_list,
+ jvmtiError *results)
+ { return p->SuspendThreadList (this, request_count, request_list, results); }
+
+ jvmtiError ResumeThreadList (jint request_count,
+ const jthread *request_list,
+ jvmtiError *results)
+ { return p->ResumeThreadList (this, request_count, request_list, results); }
+
+ jvmtiError GetAllStackTraces (jint max_frame_count,
+ jvmtiStackInfo **stack_info_ptr,
+ jint *thread_count_ptr)
+ {
+ return p->GetAllStackTraces (this, max_frame_count, stack_info_ptr,
+ thread_count_ptr);
+ }
+
+ jvmtiError GetThreadListStackTraces (jint thread_count,
+ const jthread *thread_list,
+ jint max_frame_count,
+ jvmtiStackInfo **stack_info_ptr)
+ {
+ return p->GetThreadListStackTraces (this, thread_count, thread_list,
+ max_frame_count, stack_info_ptr);
+ }
+
+ jvmtiError GetThreadLocalStorage (jthread thread, void **data_ptr)
+ { return p->GetThreadLocalStorage (this, thread, data_ptr); }
+
+ jvmtiError SetThreadLocalStorage (jthread thread, const void *data)
+ { return p->SetThreadLocalStorage (this, thread, data); }
+
+ jvmtiError GetStackTrace (jthread thread, jint start_depth,
+ jint max_frame_count,
+ jvmtiFrameInfo *frame_buffer, jint *count_ptr)
+ {
+ return p->GetStackTrace (this, thread, start_depth, max_frame_count,
+ frame_buffer, count_ptr);
+ }
+
+ jvmtiError GetTag (jobject object, jlong *tag_ptr)
+ { return p->GetTag (this, object, tag_ptr); }
+
+ jvmtiError SetTag (jobject object, jlong tag)
+ { return p->SetTag (this, object, tag); }
+
+ jvmtiError ForceGarbageCollection (void)
+ { return p->ForceGarbageCollection (this); }
+
+ jvmtiError IterateOverObjectsReachableFromObject (jobject object,
+ jvmtiObjectReferenceCallback object_reference_callback,
+ void *user_data)
+ {
+ return p->IterateOverObjectsReachableFromObject (this, object,
+ object_reference_callback,
+ user_data);
+ }
+
+ jvmtiError IterateOverReachableObjects (jvmtiHeapRootCallback heap_root_callback,
+ jvmtiStackReferenceCallback stack_ref_callback,
+ jvmtiObjectReferenceCallback object_ref_callback,
+ void *user_data)
+ {
+ return p->IterateOverReachableObjects (this, heap_root_callback,
+ stack_ref_callback,
+ object_ref_callback,
+ user_data);
+ }
+
+ jvmtiError IterateOverHeap (jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ void *user_data)
+ {
+ return p->IterateOverHeap (this, object_filter, heap_object_callback,
+ user_data);
+ }
+
+ jvmtiError IterateOverInstanceOfClass (jclass klass,
+ jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ void *user_data)
+ {
+ return p->IterateOverInstanceOfClass (this, klass, object_filter,
+ heap_object_callback, user_data);
+ }
+
+ jvmtiError GetObjectsWithTags (jint tag_count, const jlong *tags,
+ jint *count_ptr, jobject **object_result_ptr,
+ jlong **tag_result_ptr)
+ {
+ return p->GetObjectsWithTags (this, tag_count, tags, count_ptr,
+ object_result_ptr, tag_result_ptr);
+ }
+
+ jvmtiError SetJNIFunctionTable (const jniNativeInterface *function_table)
+ { return p->SetJNIFunctionTable (this, function_table); }
+
+ jvmtiError GetJNIFunctionTable (jniNativeInterface **function_table_ptr)
+ { return p->GetJNIFunctionTable (this, function_table_ptr); }
+
+ jvmtiError SetEventCallbacks (const jvmtiEventCallbacks *callbacks,
+ jint size_of_callbacks)
+ { return p->SetEventCallbacks (this, callbacks, size_of_callbacks); }
+
+ jvmtiError GenerateEvents (jvmtiEvent event_type)
+ { return p->GenerateEvents (this, event_type); }
+
+ jvmtiError GetExtensionFunctions (jint *extension_count_ptr,
+ jvmtiExtensionFunctionInfo **extensions)
+ { return p->GetExtensionFunctions (this, extension_count_ptr, extensions); }
+
+ jvmtiError GetExtensionEvents (jint *extension_count_ptr,
+ jvmtiExtensionEventInfo **extensions)
+ { return p->GetExtensionEvents (this, extension_count_ptr, extensions); }
+
+ jvmtiError SetExtensionEventCallback (jint extension_event_index,
+ jvmtiExtensionEvent callback)
+ {
+ return p->SetExtensionEventCallback (this, extension_event_index,
+ callback);
+ }
+
+ jvmtiError DisposeEnvironment (void)
+ { return p->DisposeEnvironment (this); }
+
+ jvmtiError GetErrorName (jvmtiError error, char **name_ptr)
+ { return p->GetErrorName (this, error, name_ptr); }
+
+ jvmtiError GetJLocationFormat (jvmtiJlocationFormat *format_ptr)
+ { return p->GetJLocationFormat (this, format_ptr); }
+
+ jvmtiError GetSystemProperties (jint *count_ptr, char ***property_ptr)
+ { return p->GetSystemProperties (this, count_ptr, property_ptr); }
+
+ jvmtiError GetSystemProperty (const char *property, char **value_ptr)
+ { return p->GetSystemProperty (this, property, value_ptr); }
+
+ jvmtiError SetSystemProperty (const char *property, const char *value)
+ { return p->SetSystemProperty (this, property, value); }
+
+ jvmtiError GetPhase (jvmtiPhase *phase_ptr)
+ { return p->GetPhase (this, phase_ptr); }
+
+ jvmtiError GetCurrentThreadCpuTimerInfo (jvmtiTimerInfo *info_ptr)
+ { return p->GetCurrentThreadCpuTimerInfo (this, info_ptr); }
+
+ jvmtiError GetCurrentThreadCpuTime (jlong *nanos_ptr)
+ { return p->GetCurrentThreadCpuTime (this, nanos_ptr); }
+
+ jvmtiError GetThreadCpuTimerInfo (jvmtiTimerInfo *info_ptr)
+ { return p->GetThreadCpuTimerInfo (this, info_ptr); }
+
+ jvmtiError GetThreadCpuTime (jthread thread, jlong *nanos_ptr)
+ { return p->GetThreadCpuTime (this, thread, nanos_ptr); }
+
+ jvmtiError GetTimerInfo (jvmtiTimerInfo *info_ptr)
+ { return p->GetTimerInfo (this, info_ptr); }
+
+ jvmtiError GetTime (jlong *nanos_ptr)
+ {return p->GetTime (this, nanos_ptr); }
+
+ jvmtiError GetPotentialCapabilities (jvmtiCapabilities *capabilities_ptr)
+ { return p->GetPotentialCapabilities (this, capabilities_ptr); }
+
+ jvmtiError AddCapabilities (const jvmtiCapabilities *capabilities_ptr)
+ { return p->AddCapabilities (this, capabilities_ptr); }
+
+ jvmtiError RelinquishCapabilities (const jvmtiCapabilities *capabilities_ptr)
+ { return p->RelinquishCapabilities (this, capabilities_ptr); }
+
+ jvmtiError GetAvailableProcessors (jint *processor_count_ptr)
+ { return p->GetAvailableProcessors (this, processor_count_ptr); }
+
+ jvmtiError GetEnvironmentLocalStorage (void **data_ptr)
+ { return p->GetEnvironmentLocalStorage (this, data_ptr); }
+
+ jvmtiError SetEnvironmentLocalStorage (const void *data)
+ { return p->SetEnvironmentLocalStorage (this, data); }
+
+ jvmtiError AddToBootstrapClassLoaderSearch (const char *segment)
+ { return p->AddToBootstrapClassLoaderSearch (this, segment); }
+
+ jvmtiError SetVerboseFlag (jvmtiVerboseFlag flag, jboolean value)
+ { return p->SetVerboseFlag (this, flag, value); }
+
+ jvmtiError GetObjectSize (jobject object, jlong *size_ptr)
+ { return p->GetObjectSize (this, object, size_ptr); }
+};
+#endif /* __cplusplus */
+
+/*
+ * Miscellaneous flags, constants, etc
+ */
+
+/* Class status flags */
+#define JVMTI_CLASS_STATUS_VERIFIED 1
+#define JVMTI_CLASS_STATUS_PREPARED 2
+#define JVMTI_CLASS_STATUS_INITIALIZED 4
+#define JVMTI_CLASS_STATUS_ERROR 8
+#define JVMTI_CLASS_STATUS_ARRAY 16
+#define JVMTI_CLASS_STATUS_PRIMITIVE 32
+
+/* Thread state flags */
+#define JVMTI_THREAD_STATE_ALIVE 0x0001
+#define JVMTI_THREAD_STATE_TERMINATED 0x0002
+#define JVMTI_THREAD_STATE_RUNNABLE 0x0004
+#define JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER 0x0400
+#define JVMTI_THREAD_STATE_WAITING 0x0080
+#define JVMTI_THREAD_STATE_WAITING_INDEFINITELY 0x0010
+#define JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT 0x0020
+#define JVMTI_THREAD_STATE_SLEEPING 0x0040
+#define JVMTI_THREAD_STATE_IN_OBJECT_WAIT 0x0100
+#define JVMTI_THREAD_STATE_PARKED 0x0200
+#define JVMTI_THREAD_STATE_SUSPENDED 0x100000
+#define JVMTI_THREAD_STATE_INTERRUPTED 0x200000
+#define JVMTI_THREAD_STATE_IN_NATIVE 0x400000
+#define JVMTI_THREAD_STATE_VENDOR_1 0x10000000
+#define JVMTI_THREAD_STATE_VENDOR_2 0x20000000
+#define JVMTI_THREAD_STATE_VENDOR_3 0x40000000
+
+/* java.lang.Thread.State conversion masks */
+#define JVMTI_JAVA_LANG_THREAD_STATE_MASK \
+ (JVMTI_THREAD_STATE_TERMINATED \
+ | JVMTI_THREAD_STATE_ALIVE \
+ | JVMTI_THREAD_STATE_RUNNABLE \
+ | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER \
+ | JVMTI_THREAD_STATE_WAITING \
+ | JVMTI_THREAD_STATE_WAITING_INDEFINITELY \
+ | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT)
+#define JVMTI_JAVA_LANG_THREAD_STATE_NEW 0
+#define JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED JVMTI_THREAD_STATE_TERMINATED
+#define JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE \
+ (JVMTI_THREAD_STATE_ALIVE \
+ | JVMTI_THREAD_STATE_RUNNABLE)
+#define JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED \
+ (JVMTI_THREAD_STATE_ALIVE \
+ | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER)
+#define JVMTI_JAVA_LANG_THREAD_STATE_WAITING \
+ (JVMTI_THREAD_STATE_ALIVE \
+ | JVMTI_THREAD_STATE_WAITING \
+ | JVMTI_THREAD_STATE_WAITING_INDEFINITELY)
+#define JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING \
+ (JVMTI_THREAD_STATE_ALIVE \
+ | JVMTI_THREAD_STATE_WAITING \
+ | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT)
+
+/* Thread priorities */
+#define JVMTI_THREAD_MIN_PRIORITY 1
+#define JVMTI_THREAD_NORM_PRIORITY 5
+#define JVMTI_THREAD_MAX_PRIORITY 10
+
+/* Keep c-font-lock-extra-types in order: JNI followed by JVMTI,
+ all in alphabetical order */
+/* Local Variables: */
+/* c-font-lock-extra-types: ("\\sw+_t"
+ "JNIEnv" "JNINativeMethod" "JavaVM" "JavaVMOption" "jarray"
+ "jboolean" "jbooleanArray" "jbyte" "jbyteArray" "jchar" "jcharArray"
+ "jclass" "jdouble" "jdoubleArray" "jfieldID" "jfloat" "jfloatArray"
+ "jint" "jintArray" "jlong" "jlongArray" "jmethodID" "jobject" "jstring" "jthrowable"
+ "jvalue" "jweak"
+ "jvmtiEnv" "jvmtiError"
+ "jthread" "jthreadGroup" "jlocation" "jrawMonitorID") */
+/* End: */
+#endif /* !_CLASSPATH_JVMTI_H */
diff --git a/java/awt/AWTEvent.java b/java/awt/AWTEvent.java
index d10433cb3..a6151b424 100644
--- a/java/awt/AWTEvent.java
+++ b/java/awt/AWTEvent.java
@@ -103,6 +103,11 @@ public abstract class AWTEvent extends EventObject
*/
byte[] bdata;
+ /**
+ * Indicates if this event is dispatched by the KeyboardFocusManager.
+ */
+ boolean isFocusManagerEvent = false;
+
/** Mask for selecting component events. */
public static final long COMPONENT_EVENT_MASK = 0x00001;
diff --git a/java/awt/BasicStroke.java b/java/awt/BasicStroke.java
index cb8ef49ae..e6cb87e34 100644
--- a/java/awt/BasicStroke.java
+++ b/java/awt/BasicStroke.java
@@ -43,7 +43,7 @@ import gnu.java.awt.java2d.LineSegment;
import gnu.java.awt.java2d.QuadSegment;
import gnu.java.awt.java2d.Segment;
-import java.awt.geom.AffineTransform;
+import java.awt.geom.FlatteningPathIterator;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
@@ -118,6 +118,7 @@ public class BasicStroke implements Stroke
/** The dash phase. */
private final float phase;
+ // The inner and outer paths of the stroke
private Segment start, end;
/**
@@ -435,8 +436,8 @@ public class BasicStroke implements Stroke
else
addSegments(p);
- x = coords[0];
- y = coords[1];
+ x = coords[2];
+ y = coords[3];
break;
case PathIterator.SEG_CUBICTO:
@@ -452,17 +453,25 @@ public class BasicStroke implements Stroke
else
addSegments(p);
- x = coords[0];
- y = coords[1];
+ x = coords[4];
+ y = coords[5];
break;
case PathIterator.SEG_CLOSE:
- p = (new LineSegment(x, y, x0, y0)).getDisplacedSegments(width/2.0);
- addSegments(p);
+ if (x == x0 && y == y0)
+ {
+ joinSegments(new Segment[] { start.first, end.first });
+ }
+ else
+ {
+ p = (new LineSegment(x, y, x0, y0)).getDisplacedSegments(width / 2.0);
+ addSegments(p);
+ }
convertPath(output, start);
convertPath(output, end);
start = end = null;
pathOpen = false;
+ output.setWindingRule(GeneralPath.WIND_EVEN_ODD);
break;
}
pi.next();
@@ -478,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;
}
/**
@@ -499,7 +657,7 @@ public class BasicStroke implements Stroke
}
/**
- * Convert and add the linked list of Segments in s to a GeneralPath p.
+ * Append the Segments in s to the GeneralPath p
*/
private void convertPath(GeneralPath p, Segment s)
{
@@ -527,18 +685,28 @@ public class BasicStroke implements Stroke
p.closePath();
}
-
+
/**
- * Add to segments to start and end, joining the outer pair and
+ * Add the segments to start and end (the inner and outer edges of the stroke)
*/
private void addSegments(Segment[] segments)
{
- double[] p0 = start.last.last();
+ joinSegments(segments);
+ start.add(segments[0]);
+ end.add(segments[1]);
+ }
+
+ private void joinSegments(Segment[] segments)
+ {
+ double[] p0 = start.last.cp2();
double[] p1 = new double[]{start.last.P2.getX(), start.last.P2.getY()};
- double[] p2 = new double[]{segments[0].P1.getX(), segments[0].P1.getY()};
- double[] p3 = segments[0].first();
+ double[] p2 = new double[]{segments[0].first.P1.getX(), segments[0].first.P1.getY()};
+ double[] p3 = segments[0].cp1();
Point2D p;
+ p = lineIntersection(p0[0],p0[1],p1[0],p1[1],
+ p2[0],p2[1],p3[0],p3[1], false);
+
double det = (p1[0] - p0[0])*(p3[1] - p2[1]) -
(p3[0] - p2[0])*(p1[1] - p0[1]);
@@ -546,42 +714,14 @@ public class BasicStroke implements Stroke
{
// start and segment[0] form the 'inner' part of a join,
// connect the overlapping segments
- p = lineIntersection(p0[0],p0[1],p1[0],p1[1],p2[0],p2[1],p3[0],p3[1], false);
- if( p == null )
- {
- // Dodgy.
- start.add(new LineSegment(start.last.P2, segments[0].P1));
- p = new Point2D.Double((segments[0].P1.getX()+ start.last.P2.getX())/2.0,
- (segments[0].P1.getY()+ start.last.P2.getY())/2.0);
- }
- else
- segments[0].P1 = start.last.P2 = p;
-
- start.add( segments[0] );
- joinSegments(end, segments[1], p);
+ joinInnerSegments(start, segments[0], p);
+ joinOuterSegments(end, segments[1], p);
}
else
{
// end and segment[1] form the 'inner' part
- p0 = end.last.last();
- p1 = new double[]{end.last.P2.getX(), end.last.P2.getY()};
- p2 = new double[]{segments[1].P1.getX(), segments[1].P1.getY()};
- p3 = segments[1].first();
-
- p = lineIntersection(p0[0],p0[1],p1[0],p1[1],
- p2[0],p2[1],p3[0],p3[1], false);
- if( p == null )
- {
- // Dodgy.
- end.add(new LineSegment(end.last.P2, segments[1].P1));
- p = new Point2D.Double((segments[1].P1.getX()+ end.last.P2.getX())/2.0,
- (segments[1].P1.getY()+ end.last.P2.getY())/2.0);
- }
- else
- segments[1].P1 = end.last.P2 = p;
-
- end.add( segments[1] );
- joinSegments(start, segments[0], p);
+ joinInnerSegments(end, segments[1], p);
+ joinOuterSegments(start, segments[0], p);
}
}
@@ -602,7 +742,7 @@ public class BasicStroke implements Stroke
break;
case CAP_SQUARE:
- p0 = a.last.last();
+ p0 = a.last.cp2();
p1 = new double[]{a.last.P2.getX(), a.last.P2.getY()};
dx = p1[0] - p0[0];
dy = p1[1] - p0[1];
@@ -617,7 +757,7 @@ public class BasicStroke implements Stroke
break;
case CAP_ROUND:
- p0 = a.last.last();
+ p0 = a.last.cp2();
p1 = new double[]{a.last.P2.getX(), a.last.P2.getY()};
dx = p1[0] - p0[0];
dy = p1[1] - p0[1];
@@ -676,7 +816,7 @@ public class BasicStroke implements Stroke
* insideP is the inside intersection point of the join, needed for
* calculating miter lengths.
*/
- private void joinSegments(Segment a, Segment b, Point2D insideP)
+ private void joinOuterSegments(Segment a, Segment b, Point2D insideP)
{
double[] p0, p1;
double dx, dy, l;
@@ -685,10 +825,10 @@ public class BasicStroke implements Stroke
switch( join )
{
case JOIN_MITER:
- p0 = a.last.last();
+ p0 = a.last.cp2();
p1 = new double[]{a.last.P2.getX(), a.last.P2.getY()};
double[] p2 = new double[]{b.P1.getX(), b.P1.getY()};
- double[] p3 = b.first();
+ double[] p3 = b.cp1();
Point2D p = lineIntersection(p0[0],p0[1],p1[0],p1[1],p2[0],p2[1],p3[0],p3[1], true);
if( p == null || insideP == null )
a.add(new LineSegment(a.last.P2, b.P1));
@@ -705,7 +845,7 @@ public class BasicStroke implements Stroke
break;
case JOIN_ROUND:
- p0 = a.last.last();
+ p0 = a.last.cp2();
p1 = new double[]{a.last.P2.getX(), a.last.P2.getY()};
dx = p1[0] - p0[0];
dy = p1[1] - p0[1];
@@ -715,7 +855,7 @@ public class BasicStroke implements Stroke
c1 = new Point2D.Double(p1[0] + dx, p1[1] + dy);
p0 = new double[]{b.P1.getX(), b.P1.getY()};
- p1 = b.first();
+ p1 = b.cp1();
dx = p0[0] - p1[0]; // backwards direction.
dy = p0[1] - p1[1];
@@ -730,6 +870,29 @@ public class BasicStroke implements Stroke
a.add(new LineSegment(a.last.P2, b.P1));
break;
}
- a.add(b);
}
-}
+
+ /**
+ * Join a and b segments, removing any overlap
+ */
+ private void joinInnerSegments(Segment a, Segment b, Point2D p)
+ {
+ double[] p0 = a.last.cp2();
+ double[] p1 = new double[] { a.last.P2.getX(), a.last.P2.getY() };
+ double[] p2 = new double[] { b.P1.getX(), b.P1.getY() };
+ double[] p3 = b.cp1();
+
+ if (p == null)
+ {
+ // Dodgy.
+ a.add(new LineSegment(a.last.P2, b.P1));
+ p = new Point2D.Double((b.P1.getX() + a.last.P2.getX()) / 2.0,
+ (b.P1.getY() + a.last.P2.getY()) / 2.0);
+ }
+ else
+ // This assumes segments a and b are single segments, which is
+ // incorrect - if they are a linked list of segments (ie, passed in
+ // from a flattening operation), this produces strange results!!
+ a.last.P2 = b.P1 = p;
+ }
+}
diff --git a/java/awt/Canvas.java b/java/awt/Canvas.java
index 2f838d60e..843fded44 100644
--- a/java/awt/Canvas.java
+++ b/java/awt/Canvas.java
@@ -350,9 +350,9 @@ public class Canvas
}
/**
- * Generate a unique name for this canvas.
+ * Generate a unique name for this <code>Canvas</code>.
*
- * @return A unique name for this canvas.
+ * @return A unique name for this <code>Canvas</code>.
*/
String generateName()
{
diff --git a/java/awt/CardLayout.java b/java/awt/CardLayout.java
index 8b3fea2ca..7b733c821 100644
--- a/java/awt/CardLayout.java
+++ b/java/awt/CardLayout.java
@@ -350,6 +350,7 @@ public class CardLayout implements LayoutManager2, Serializable
}
}
((Component) target).setVisible (true);
+ parent.validate();
}
}
@@ -360,7 +361,7 @@ public class CardLayout implements LayoutManager2, Serializable
*/
public String toString ()
{
- return getClass ().getName () + "[" + hgap + "," + vgap + "]";
+ return getClass ().getName () + "[hgap=" + hgap + ",vgap=" + vgap + "]";
}
/**
@@ -400,11 +401,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)
{
@@ -412,11 +413,11 @@ 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);
diff --git a/java/awt/CheckboxMenuItem.java b/java/awt/CheckboxMenuItem.java
index 197065f65..2df621b71 100644
--- a/java/awt/CheckboxMenuItem.java
+++ b/java/awt/CheckboxMenuItem.java
@@ -63,6 +63,11 @@ public class CheckboxMenuItem extends MenuItem
* Static Variables
*/
+/**
+ * The number used to generate the name returned by getName.
+ */
+private static transient long next_chkmenuitem_number;
+
// Serialization constant
private static final long serialVersionUID = 6190621106981774043L;
@@ -352,6 +357,21 @@ paramString()
accessibleContext = new AccessibleAWTCheckboxMenuItem();
return accessibleContext;
}
+
+ /**
+ * Generate a unique name for this <code>CheckboxMenuItem</code>.
+ *
+ * @return A unique name for this <code>CheckboxMenuItem</code>.
+ */
+ String generateName()
+ {
+ return "chkmenuitem" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_chkmenuitem_number++;
+ }
} // class CheckboxMenuItem
diff --git a/java/awt/Choice.java b/java/awt/Choice.java
index 90a8d3141..b3319af2f 100644
--- a/java/awt/Choice.java
+++ b/java/awt/Choice.java
@@ -1,5 +1,5 @@
/* Choice.java -- Java choice button widget.
- Copyright (C) 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -51,51 +51,47 @@ import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
/**
- * This class implements a drop down choice list.
- *
- * @author Aaron M. Renn (arenn@urbanophile.com)
- */
+ * This class implements a drop down choice list.
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
public class Choice extends Component
implements ItemSelectable, Serializable, Accessible
{
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_choice_number;
-/*
- * Static Variables
- */
-
-// Serialization constant
-private static final long serialVersionUID = -4075310674757313071L;
-
-/*************************************************************************/
-
-/*
- * Instance Variables
- */
+ // Serialization constant
+ private static final long serialVersionUID = -4075310674757313071L;
-/**
- * @serial A list of items for the choice box, which can be <code>null</code>.
- * This is package-private to avoid an accessor method.
- */
-Vector pItems = new Vector();
+ /**
+ * @serial A list of items for the choice box, which can be <code>null</code>.
+ * This is package-private to avoid an accessor method.
+ */
+ Vector pItems = new Vector();
-/**
- * @serial The index of the selected item in the choice box.
- */
-private int selectedIndex = -1;
+ /**
+ * @serial The index of the selected item in the choice box.
+ */
+ private int selectedIndex = -1;
-// Listener chain
-private ItemListener item_listeners;
+ /**
+ * ItemListener chain
+ */
+ private ItemListener item_listeners;
-/**
- * This class provides accessibility support for the
- * combo box.
- *
- * @author Jerry Quinn (jlquinn@optonline.net)
- * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
- */
+ /**
+ * This class provides accessibility support for the
+ * combo box.
+ *
+ * @author Jerry Quinn (jlquinn@optonline.net)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
protected class AccessibleAWTChoice
- extends AccessibleAWTComponent
- implements AccessibleAction
+ extends AccessibleAWTComponent
+ implements AccessibleAction
{
/**
@@ -181,19 +177,12 @@ private ItemListener item_listeners;
if (i < 0 || i >= pItems.size())
return false;
- Choice.this.processItemEvent(new ItemEvent(Choice.this,
- ItemEvent.ITEM_STATE_CHANGED,
- this, ItemEvent.SELECTED));
+ Choice.this.select( i );
+
return true;
}
}
-/*************************************************************************/
-
-/*
- * Constructors
- */
-
/**
* Initializes a new instance of <code>Choice</code>.
*
@@ -206,397 +195,320 @@ private ItemListener item_listeners;
throw new HeadlessException ();
}
-/*************************************************************************/
-
-/*
- * Instance Methods
- */
-
-/**
- * Returns the number of items in the list.
- *
- * @return The number of items in the list.
- */
-public int
-getItemCount()
-{
- return countItems ();
-}
-
-/*************************************************************************/
-
-/**
- * Returns the number of items in the list.
- *
- * @return The number of items in the list.
- *
- * @deprecated This method is deprecated in favor of <code>getItemCount</code>.
- */
-public int
-countItems()
-{
- return(pItems.size());
-}
-
-/*************************************************************************/
-
-/**
- * Returns the item at the specified index in the list.
- *
- * @param index The index into the list to return the item from.
- *
- * @exception ArrayIndexOutOfBoundsException If the index is invalid.
- */
-public String
-getItem(int index)
-{
- return((String)pItems.elementAt(index));
-}
-
-/*************************************************************************/
-
-/**
- * Adds the specified item to this choice box.
- *
- * @param item The item to add.
- *
- * @exception NullPointerException If the item's value is null
- *
- * @since 1.1
- */
-public synchronized void
-add(String item)
-{
- if (item == null)
- throw new NullPointerException ("item must be non-null");
-
- pItems.addElement(item);
-
- int i = pItems.size () - 1;
- if (peer != null)
- {
- ChoicePeer cp = (ChoicePeer) peer;
- cp.add (item, i);
- }
- else if (selectedIndex == -1)
- select(0);
-}
-
-/*************************************************************************/
+ /**
+ * Returns the number of items in the list.
+ *
+ * @return The number of items in the list.
+ */
+ public int getItemCount()
+ {
+ return countItems ();
+ }
-/**
- * Adds the specified item to this choice box.
- *
- * This method is oboslete since Java 2 platform 1.1. Please use @see add
- * instead.
- *
- * @param item The item to add.
- *
- * @exception NullPointerException If the item's value is equal to null
- */
-public synchronized void
-addItem(String item)
-{
- add(item);
-}
+ /**
+ * Returns the number of items in the list.
+ *
+ * @return The number of items in the list.
+ *
+ * @deprecated This method is deprecated in favor of <code>getItemCount</code>.
+ */
+ public int countItems()
+ {
+ return pItems.size();
+ }
-/*************************************************************************/
+ /**
+ * Returns the item at the specified index in the list.
+ *
+ * @param index The index into the list to return the item from.
+ *
+ * @exception ArrayIndexOutOfBoundsException If the index is invalid.
+ */
+ public String getItem(int index)
+ {
+ return (String)pItems.elementAt(index);
+ }
-/** Inserts an item into this Choice. Existing items are shifted
- * upwards. If the new item is the only item, then it is selected.
- * If the currently selected item is shifted, then the first item is
- * selected. If the currently selected item is not shifted, then it
- * remains selected.
- *
- * @param item The item to add.
- * @param index The index at which the item should be inserted.
- *
- * @exception IllegalArgumentException If index is less than 0
- */
-public synchronized void
-insert(String item, int index)
-{
- if (index < 0)
- throw new IllegalArgumentException ("index may not be less then 0");
+ /**
+ * Adds the specified item to this choice box.
+ *
+ * @param item The item to add.
+ *
+ * @exception NullPointerException If the item's value is null
+ *
+ * @since 1.1
+ */
+ public synchronized void add(String item)
+ {
+ if (item == null)
+ throw new NullPointerException ("item must be non-null");
- if (index > getItemCount ())
- index = getItemCount ();
+ pItems.addElement(item);
- pItems.insertElementAt(item, index);
+ if (peer != null)
+ ((ChoicePeer) peer).add(item, getItemCount() - 1);
- if (peer != null)
- {
- ChoicePeer cp = (ChoicePeer) peer;
- cp.add (item, index);
- }
- else if (selectedIndex == -1 || selectedIndex >= index)
- select(0);
-}
+ if (selectedIndex == -1)
+ select( 0 );
+ }
-/*************************************************************************/
+ /**
+ * Adds the specified item to this choice box.
+ *
+ * This method is oboslete since Java 2 platform 1.1. Please use @see add
+ * instead.
+ *
+ * @param item The item to add.
+ *
+ * @exception NullPointerException If the item's value is equal to null
+ */
+ public synchronized void addItem(String item)
+ {
+ add(item);
+ }
-/**
- * Removes the specified item from the choice box.
- *
- * @param item The item to remove.
- *
- * @exception IllegalArgumentException If the specified item doesn't exist.
- */
-public synchronized void
-remove(String item)
-{
- int index = pItems.indexOf(item);
- if (index == -1)
- throw new IllegalArgumentException ("item \""
- + item + "\" not found in Choice");
- remove(index);
-}
+ /** Inserts an item into this Choice. Existing items are shifted
+ * upwards. If the new item is the only item, then it is selected.
+ * If the currently selected item is shifted, then the first item is
+ * selected. If the currently selected item is not shifted, then it
+ * remains selected.
+ *
+ * @param item The item to add.
+ * @param index The index at which the item should be inserted.
+ *
+ * @exception IllegalArgumentException If index is less than 0
+ */
+ public synchronized void insert(String item, int index)
+ {
+ if (index < 0)
+ throw new IllegalArgumentException ("index may not be less then 0");
-/*************************************************************************/
+ if (index > getItemCount ())
+ index = getItemCount ();
-/**
- * Removes the item at the specified index from the choice box.
- *
- * @param index The index of the item to remove.
- *
- * @exception IndexOutOfBoundsException If the index is not valid.
- */
-public synchronized void
-remove(int index)
-{
- if ((index < 0) || (index > getItemCount()))
- throw new IllegalArgumentException("Bad index: " + index);
+ pItems.insertElementAt(item, index);
- pItems.removeElementAt(index);
+ if (peer != null)
+ ((ChoicePeer) peer).add (item, index);
- if (peer != null)
- {
- ChoicePeer cp = (ChoicePeer) peer;
- cp.remove (index);
- }
- else
- {
- if (getItemCount() == 0)
- selectedIndex = -1;
- else if (index == selectedIndex)
- select(0);
- }
+ if (selectedIndex == -1 || selectedIndex >= index)
+ select(0);
+ }
- if (selectedIndex > index)
- --selectedIndex;
-}
+ /**
+ * Removes the specified item from the choice box.
+ *
+ * @param item The item to remove.
+ *
+ * @exception IllegalArgumentException If the specified item doesn't exist.
+ */
+ public synchronized void remove(String item)
+ {
+ int index = pItems.indexOf(item);
+ if (index == -1)
+ throw new IllegalArgumentException ("item \""
+ + item + "\" not found in Choice");
+ remove(index);
+ }
-/*************************************************************************/
+ /**
+ * Removes the item at the specified index from the choice box.
+ *
+ * @param index The index of the item to remove.
+ *
+ * @exception IndexOutOfBoundsException If the index is not valid.
+ */
+ public synchronized void remove(int index)
+ {
+ pItems.removeElementAt(index);
+
+ if (peer != null)
+ ((ChoicePeer) peer).remove( index );
+
+ if( getItemCount() == 0 )
+ selectedIndex = -1;
+ else
+ {
+ if( selectedIndex > index )
+ selectedIndex--;
+ else if( selectedIndex == index )
+ selectedIndex = 0;
+
+ if( peer != null )
+ ((ChoicePeer)peer).select( selectedIndex );
+ }
+ }
-/**
- * Removes all of the objects from this choice box.
- */
-public synchronized void
-removeAll()
-{
- if (getItemCount() <= 0)
- return;
+ /**
+ * Removes all of the objects from this choice box.
+ */
+ public synchronized void removeAll()
+ {
+ if (getItemCount() <= 0)
+ return;
- pItems.removeAllElements ();
-
- if (peer != null)
- {
- ChoicePeer cp = (ChoicePeer) peer;
- cp.removeAll ();
- }
-
- selectedIndex = -1;
-}
-
-/*************************************************************************/
+ pItems.removeAllElements ();
-/**
- * Returns the currently selected item, or null if no item is
- * selected.
- *
- * @return The currently selected item.
- */
-public synchronized String
-getSelectedItem()
-{
- return (selectedIndex == -1
- ? null
- : ((String)pItems.elementAt(selectedIndex)));
-}
-
-/*************************************************************************/
-
-/**
- * Returns an array with one row containing the selected item.
- *
- * @return An array containing the selected item.
- */
-public synchronized Object[]
-getSelectedObjects()
-{
- if (selectedIndex == -1)
- return null;
-
- Object[] objs = new Object[1];
- objs[0] = pItems.elementAt(selectedIndex);
+ if (peer != null)
+ {
+ ChoicePeer cp = (ChoicePeer) peer;
+ cp.removeAll ();
+ }
- return(objs);
-}
+ selectedIndex = -1;
+ }
-/*************************************************************************/
+ /**
+ * Returns the currently selected item, or null if no item is
+ * selected.
+ *
+ * @return The currently selected item.
+ */
+ public synchronized String getSelectedItem()
+ {
+ return (selectedIndex == -1
+ ? null
+ : ((String)pItems.elementAt(selectedIndex)));
+ }
-/**
- * Returns the index of the selected item.
- *
- * @return The index of the selected item.
- */
-public int
-getSelectedIndex()
-{
- return(selectedIndex);
-}
+ /**
+ * Returns an array with one row containing the selected item.
+ *
+ * @return An array containing the selected item.
+ */
+ public synchronized Object[] getSelectedObjects()
+ {
+ if (selectedIndex == -1)
+ return null;
-/*************************************************************************/
+ Object[] objs = new Object[1];
+ objs[0] = pItems.elementAt(selectedIndex);
-/**
- * Forces the item at the specified index to be selected.
- *
- * @param index The index of the row to make selected.
- *
- * @exception IllegalArgumentException If the specified index is invalid.
- */
-public synchronized void
-select(int index)
-{
- if ((index < 0) || (index >= getItemCount()))
- throw new IllegalArgumentException("Bad index: " + index);
-
- if (pItems.size() > 0) {
- selectedIndex = index;
- ChoicePeer cp = (ChoicePeer) peer;
- if (cp != null) {
- cp.select(index);
- }
+ return objs;
}
-}
-/*************************************************************************/
+ /**
+ * Returns the index of the selected item.
+ *
+ * @return The index of the selected item.
+ */
+ public int getSelectedIndex()
+ {
+ return selectedIndex;
+ }
-/**
- * Forces the named item to be selected.
- *
- * @param item The item to be selected.
- *
- * @exception IllegalArgumentException If the specified item does not exist.
- */
-public synchronized void
-select(String item)
-{
- int index = pItems.indexOf(item);
- if (index >= 0)
- select(index);
-}
+ /**
+ * Forces the item at the specified index to be selected.
+ *
+ * @param index The index of the row to make selected.
+ *
+ * @exception IllegalArgumentException If the specified index is invalid.
+ */
+ public synchronized void select(int index)
+ {
+ if ((index < 0) || (index >= getItemCount()))
+ throw new IllegalArgumentException("Bad index: " + index);
-/*************************************************************************/
+ if( selectedIndex == index )
+ return;
-/**
- * Creates the native peer for this object.
- */
-public void
-addNotify()
-{
- if (peer == null)
- peer = getToolkit ().createChoice (this);
- super.addNotify ();
-}
+ selectedIndex = index;
+ if( peer != null )
+ ((ChoicePeer)peer).select( index );
+ }
-/*************************************************************************/
+ /**
+ * Forces the named item to be selected.
+ *
+ * @param item The item to be selected.
+ *
+ * @exception IllegalArgumentException If the specified item does not exist.
+ */
+ public synchronized void select(String item)
+ {
+ int index = pItems.indexOf(item);
+ if( index >= 0 )
+ select( index );
+ }
-/**
- * Adds the specified listener 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);
-}
+ /**
+ * Creates the native peer for this object.
+ */
+ public void addNotify()
+ {
+ if (peer == null)
+ peer = getToolkit ().createChoice (this);
+ super.addNotify ();
+ }
-/*************************************************************************/
+ /**
+ * Adds the specified listener 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);
+ }
-/**
- * Removes the specified listener from the list of registered listeners for
- * this object.
- *
- * @param listener The listener to remove.
- */
-public synchronized void
-removeItemListener(ItemListener listener)
-{
- item_listeners = AWTEventMulticaster.remove(item_listeners, listener);
-}
+ /**
+ * Removes the specified listener from the list of registered listeners for
+ * this object.
+ *
+ * @param listener The listener to remove.
+ */
+ public synchronized void removeItemListener(ItemListener listener)
+ {
+ item_listeners = AWTEventMulticaster.remove(item_listeners, listener);
+ }
-/*************************************************************************/
+ /**
+ * Processes this event by invoking <code>processItemEvent()</code> if the
+ * event is an instance of <code>ItemEvent</code>, otherwise the event
+ * is passed to the superclass.
+ *
+ * @param event The event to process.
+ */
+ protected void processEvent(AWTEvent event)
+ {
+ if (event instanceof ItemEvent)
+ processItemEvent((ItemEvent)event);
+ else
+ super.processEvent(event);
+ }
-/**
- * Processes this event by invoking <code>processItemEvent()</code> if the
- * event is an instance of <code>ItemEvent</code>, otherwise the event
- * is passed to the superclass.
- *
- * @param event The event to process.
- */
-protected void
-processEvent(AWTEvent event)
-{
- if (event instanceof ItemEvent)
- processItemEvent((ItemEvent)event);
- else
- super.processEvent(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
+ void dispatchEventImpl(AWTEvent e)
+ {
super.dispatchEventImpl(e);
-}
-/*************************************************************************/
-
-/**
- * Processes item event by dispatching to any registered listeners.
- *
- * @param event The event to process.
- */
-protected void
-processItemEvent(ItemEvent event)
-{
- int index = pItems.indexOf((String) event.getItem());
- // Don't call back into the peers when selecting index here
- if (event.getStateChange() == ItemEvent.SELECTED)
- this.selectedIndex = index;
- if (item_listeners != null)
- item_listeners.itemStateChanged(event);
-}
+ if( e.id <= ItemEvent.ITEM_LAST && e.id >= ItemEvent.ITEM_FIRST &&
+ ( item_listeners != null ||
+ ( eventMask & AWTEvent.ITEM_EVENT_MASK ) != 0 ) )
+ processEvent(e);
+ }
-/*************************************************************************/
+ /**
+ * Processes item event by dispatching to any registered listeners.
+ *
+ * @param event The event to process.
+ */
+ protected void processItemEvent(ItemEvent event)
+ {
+ int index = pItems.indexOf((String) event.getItem());
+ if (item_listeners != null)
+ item_listeners.itemStateChanged(event);
+ }
-/**
- * Returns a debugging string for this object.
- *
- * @return A debugging string for this object.
- */
-protected String
-paramString()
-{
- return ("selectedIndex=" + selectedIndex + "," + super.paramString());
-}
+ /**
+ * Returns a debugging string for this object.
+ *
+ * @return A debugging string for this object.
+ */
+ protected String paramString()
+ {
+ return "selectedIndex=" + selectedIndex + "," + super.paramString();
+ }
/**
* Returns an array of all the objects currently registered as FooListeners
@@ -639,4 +551,19 @@ paramString()
accessibleContext = new AccessibleAWTChoice();
return accessibleContext;
}
+
+ /**
+ * Generate a unique name for this <code>Choice</code>.
+ *
+ * @return A unique name for this <code>Choice</code>.
+ */
+ String generateName()
+ {
+ return "choice" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_choice_number++;
+ }
} // class Choice
diff --git a/java/awt/Component.java b/java/awt/Component.java
index 5f4a27c6a..4b4c390d4 100644
--- a/java/awt/Component.java
+++ b/java/awt/Component.java
@@ -39,6 +39,8 @@ exception statement from your version. */
package java.awt;
+//import gnu.java.awt.dnd.peer.gtk.GtkDropTargetContextPeer;
+
import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
import java.awt.event.AdjustmentEvent;
@@ -214,6 +216,12 @@ public abstract class Component
*/
static final Object treeLock = new String("AWT_TREE_LOCK");
+ /**
+ * The default maximum size.
+ */
+ private static final Dimension DEFAULT_MAX_SIZE
+ = new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
+
// Serialized fields from the serialization spec.
/**
@@ -588,6 +596,17 @@ public abstract class Component
transient BufferStrategy bufferStrategy;
/**
+ * The number of hierarchy listeners of this container plus all of its
+ * children. This is needed for efficient handling of HierarchyEvents.
+ * These must be propagated to all child components with HierarchyListeners
+ * attached. To avoid traversal of the whole subtree, we keep track of
+ * the number of HierarchyListeners here and only walk the paths that
+ * actually have listeners.
+ */
+ int numHierarchyListeners;
+ int numHierarchyBoundsListeners;
+
+ /**
* true if requestFocus was called on this component when its
* top-level ancestor was not focusable.
*/
@@ -681,6 +700,9 @@ public abstract class Component
public void setDropTarget(DropTarget dt)
{
this.dropTarget = dt;
+
+ if (peer != null)
+ dropTarget.addNotify(peer);
}
/**
@@ -724,16 +746,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;
}
/**
@@ -834,9 +863,17 @@ public abstract class Component
*/
public void enable()
{
- this.enabled = true;
- if (peer != null)
- peer.setEnabled (true);
+ if (! enabled)
+ {
+ // Need to lock the tree here, because the peers are involved.
+ synchronized (getTreeLock())
+ {
+ enabled = true;
+ ComponentPeer p = peer;
+ if (p != null)
+ p.enable();
+ }
+ }
}
/**
@@ -861,9 +898,17 @@ public abstract class Component
*/
public void disable()
{
- this.enabled = false;
- if (peer != null)
- peer.setEnabled (false);
+ if (enabled)
+ {
+ // Need to lock the tree here, because the peers are involved.
+ synchronized (getTreeLock())
+ {
+ enabled = false;
+ ComponentPeer p = peer;
+ if (p != null)
+ p.disable();
+ }
+ }
}
/**
@@ -928,15 +973,38 @@ public abstract class Component
// and its children.
if(!isVisible())
{
- this.visible = true;
- // Avoid NullPointerExceptions by creating a local reference.
- ComponentPeer currentPeer=peer;
- if (currentPeer != null)
- currentPeer.show();
- // The JDK repaints the component before invalidating the parent.
- // So do we.
- if (isShowing() && isLightweight())
- repaint();
+ // 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;
+ if (currentPeer != null)
+ {
+ currentPeer.show();
+
+ // Fire HierarchyEvent.
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
+ this, parent,
+ HierarchyEvent.SHOWING_CHANGED);
+
+ // The JDK repaints the component before invalidating the parent.
+ // So do we.
+ if (isLightweight())
+ repaint();
+ }
+
+ // Only post an event if this component actually has a listener
+ // or has this event explicitly enabled.
+ if (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
+ {
+ ComponentEvent ce =
+ new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ }
+
// Invalidate the parent if we have one. The component itself must
// not be invalidated. We also avoid NullPointerException with
// a local reference here.
@@ -944,9 +1012,6 @@ public abstract class Component
if (currentParent != null)
currentParent.invalidate();
- ComponentEvent ce =
- new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN);
- getToolkit().getSystemEventQueue().postEvent(ce);
}
}
@@ -974,27 +1039,45 @@ public abstract class Component
{
if (isVisible())
{
- // Avoid NullPointerExceptions by creating a local reference.
- ComponentPeer currentPeer=peer;
- if (currentPeer != null)
- currentPeer.setVisible(false);
- boolean wasShowing = isShowing();
- this.visible = false;
-
- // The JDK repaints the component before invalidating the parent.
- // So do we.
- if (wasShowing)
- repaint();
- // Invalidate the parent if we have one. The component itself must
+ // Need to lock the tree here to avoid races and inconsistencies.
+ synchronized (getTreeLock())
+ {
+ visible = false;
+
+ // Avoid NullPointerExceptions by creating a local reference.
+ ComponentPeer currentPeer = peer;
+ if (currentPeer != null)
+ {
+ currentPeer.hide();
+
+ // Fire hierarchy event.
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
+ this, parent,
+ HierarchyEvent.SHOWING_CHANGED);
+ // The JDK repaints the component before invalidating the
+ // parent. So do we. This only applies for lightweights.
+ if (peer instanceof LightweightPeer)
+ repaint();
+ }
+
+ // Only post an event if this component actually has a listener
+ // or has this event explicitly enabled.
+ if (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
+ {
+ ComponentEvent ce =
+ new ComponentEvent(this,ComponentEvent.COMPONENT_HIDDEN);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ }
+
+ // Invalidate the parent if we have one. The component itself need
// not be invalidated. We also avoid NullPointerException with
// a local reference here.
Container currentParent = parent;
if (currentParent != null)
currentParent.invalidate();
- ComponentEvent ce =
- new ComponentEvent(this,ComponentEvent.COMPONENT_HIDDEN);
- getToolkit().getSystemEventQueue().postEvent(ce);
}
}
@@ -1215,8 +1298,33 @@ public abstract class Component
throw new IllegalComponentStateException("component "
+ getClass().getName()
+ " not showing");
- // We know peer != null here.
- return peer.getLocationOnScreen();
+
+ // Need to lock the tree here. We get crazy races and explosions when
+ // the tree changes while we are trying to find the location of this
+ // component.
+ synchronized (getTreeLock())
+ {
+ // 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;
+ }
}
/**
@@ -1410,53 +1518,81 @@ public abstract class Component
*/
public void reshape(int x, int y, int width, int height)
{
- int oldx = this.x;
- int oldy = this.y;
- int oldwidth = this.width;
- int oldheight = this.height;
+ // We need to lock the tree here, otherwise we risk races and
+ // inconsistencies.
+ synchronized (getTreeLock())
+ {
+ int oldx = this.x;
+ int oldy = this.y;
+ int oldwidth = this.width;
+ int oldheight = this.height;
- if (this.x == x && this.y == y && this.width == width
- && this.height == height)
- return;
+ boolean resized = oldwidth != width || oldheight != height;
+ boolean moved = oldx != x || oldy != y;
- invalidate();
-
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
- if (peer != null)
- peer.setBounds (x, y, width, height);
-
- // Erase old bounds and repaint new bounds for lightweights.
- if (isLightweight() && isShowing())
- {
- if (parent != null)
+ if (resized || moved)
{
- Rectangle oldBounds = new Rectangle(oldx, oldy, oldwidth,
- oldheight);
- Rectangle newBounds = new Rectangle(x, y, width, height);
- Rectangle destroyed = oldBounds.union(newBounds);
- if (!destroyed.isEmpty())
- parent.repaint(0, destroyed.x, destroyed.y, destroyed.width,
- destroyed.height);
+ // Update the fields.
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+
+ if (peer != null)
+ {
+ peer.setBounds (x, y, width, height);
+ if (resized)
+ invalidate();
+ if (parent != null && parent.valid)
+ parent.invalidate();
+ }
+
+ // Send some events to interested listeners.
+ notifyReshape(resized, moved);
+
+ // Repaint this component and the parent if appropriate.
+ if (parent != null && peer instanceof LightweightPeer
+ && isShowing())
+ {
+ // The parent repaints the area that we occupied before.
+ parent.repaint(oldx, oldy, oldwidth, oldheight);
+ // This component repaints the area that we occupy now.
+ repaint();
+ }
}
}
+ }
- // Only post event if this component is visible and has changed size.
- if (isShowing ()
- && (oldx != x || oldy != y))
+ /**
+ * 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.
+ if (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
{
- ComponentEvent ce = new ComponentEvent(this,
+ // Fire component event on this component.
+ if (moved)
+ {
+ ComponentEvent ce = new ComponentEvent(this,
ComponentEvent.COMPONENT_MOVED);
- getToolkit().getSystemEventQueue().postEvent(ce);
- }
- if (isShowing ()
- && (oldwidth != width || oldheight != height))
- {
- ComponentEvent ce = new ComponentEvent(this,
- ComponentEvent.COMPONENT_RESIZED);
- getToolkit().getSystemEventQueue().postEvent(ce);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ if (resized)
+ {
+ ComponentEvent ce = new ComponentEvent(this,
+ ComponentEvent.COMPONENT_RESIZED);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
}
}
@@ -1660,14 +1796,36 @@ public abstract class Component
*/
public Dimension preferredSize()
{
- if (!prefSizeSet)
+ // Create a new Dimension object, so that the application doesn't mess
+ // with the actual values.
+ return new Dimension(preferredSizeImpl());
+ }
+
+ /**
+ * The actual calculation is pulled out of preferredSize() so that
+ * we can call it from Container.preferredSize() and avoid creating a
+ * new intermediate Dimension object.
+ *
+ * @return the preferredSize of the component
+ */
+ Dimension preferredSizeImpl()
+ {
+ Dimension size = prefSize;
+ // Try to use a cached value.
+ if (size == null || !(valid || prefSizeSet))
{
- if (peer == null)
- prefSize = minimumSize();
- else
- prefSize = peer.getPreferredSize();
+ // We need to lock here, because the calculation depends on the
+ // component structure not changing.
+ synchronized (getTreeLock())
+ {
+ ComponentPeer p = peer;
+ if (p != null)
+ size = peer.preferredSize();
+ else
+ size = minimumSizeImpl();
+ }
}
- return prefSize;
+ return size;
}
/**
@@ -1724,10 +1882,36 @@ public abstract class Component
*/
public Dimension minimumSize()
{
- if (minSize == null)
- minSize = (peer != null ? peer.getMinimumSize()
- : new Dimension(width, height));
- return minSize;
+ // Create a new Dimension object, so that the application doesn't mess
+ // with the actual values.
+ return new Dimension(minimumSizeImpl());
+ }
+
+ /**
+ * The actual calculation is pulled out of minimumSize() so that
+ * we can call it from Container.preferredSize() and
+ * Component.preferredSizeImpl and avoid creating a
+ * new intermediate Dimension object.
+ *
+ * @return the minimum size of the component
+ */
+ Dimension minimumSizeImpl()
+ {
+ Dimension size = minSize;
+ if (size == null || !(valid || minSizeSet))
+ {
+ // We need to lock here, because the calculation depends on the
+ // component structure not changing.
+ synchronized (getTreeLock())
+ {
+ ComponentPeer p = peer;
+ if (p != null)
+ size = peer.minimumSize();
+ else
+ size = size();
+ }
+ }
+ return size;
}
/**
@@ -1741,10 +1925,24 @@ public abstract class Component
*/
public Dimension getMaximumSize()
{
+ return new Dimension(maximumSizeImpl());
+ }
+
+ /**
+ * This is pulled out from getMaximumSize(), so that we can access it
+ * from Container.getMaximumSize() without creating an additional
+ * intermediate Dimension object.
+ *
+ * @return the maximum size of the component
+ */
+ Dimension maximumSizeImpl()
+ {
+ Dimension size;
if (maxSizeSet)
- return maxSize;
+ size = maxSize;
else
- return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
+ size = DEFAULT_MAX_SIZE;
+ return size;
}
/**
@@ -1848,11 +2046,25 @@ public abstract class Component
*/
public void invalidate()
{
- valid = false;
- prefSize = null;
- minSize = null;
- if (parent != null && parent.isValid())
- parent.invalidate();
+ // Need to lock here, to avoid races and other ugly stuff when doing
+ // layout or structure changes in other threads.
+ synchronized (getTreeLock())
+ {
+ // Invalidate.
+ valid = false;
+
+ // Throw away cached layout information.
+ if (! minSizeSet)
+ minSize = null;
+ if (! prefSizeSet)
+ prefSize = null;
+ if (! maxSizeSet)
+ maxSize = null;
+
+ // Also invalidate the parent, if it hasn't already been invalidated.
+ if (parent != null && parent.isValid())
+ parent.invalidate();
+ }
}
/**
@@ -1864,21 +2076,29 @@ public abstract class Component
*/
public Graphics getGraphics()
{
- if (peer != null)
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ int offsX = 0;
+ int offsY = 0;
+ while (p instanceof LightweightPeer)
{
- Graphics gfx = peer.getGraphics();
- // Create peer for lightweights.
- if (gfx == null && parent != null)
- {
- gfx = parent.getGraphics();
- gfx.clipRect(getX(), getY(), getWidth(), getHeight());
- gfx.translate(getX(), getY());
- return gfx;
- }
+ offsX += comp.x;
+ offsY += comp.y;
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ Graphics gfx = null;
+ if (p != null)
+ {
+ assert ! (p instanceof LightweightPeer);
+ gfx = p.getGraphics();
+ gfx.translate(offsX, offsY);
+ gfx.clipRect(0, 0, width, height);
gfx.setFont(font);
- return gfx;
}
- return null;
+ return gfx;
}
/**
@@ -1892,8 +2112,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);
}
/**
@@ -1912,8 +2140,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);
}
/**
@@ -1958,11 +2196,9 @@ public abstract class Component
}
/**
- * Updates this component. This is called in response to
- * <code>repaint</code>. This method fills the component with the
- * background color, then sets the foreground color of the specified
- * graphics context to the foreground color of this component and calls
- * the <code>paint()</code> method. The coordinates of the graphics are
+ * Updates this component. This is called for heavyweight components in
+ * response to {@link #repaint()}. The default implementation simply forwards
+ * to {@link #paint(Graphics)}. The coordinates of the graphics are
* relative to this component. Subclasses should call either
* <code>super.update(g)</code> or <code>paint(g)</code>.
*
@@ -1970,27 +2206,17 @@ public abstract class Component
*
* @see #paint(Graphics)
* @see #repaint()
- *
- * @specnote In contrast to what the spec says, tests show that the exact
- * behaviour is to clear the background on lightweight and
- * top-level components only. Heavyweight components are not
- * affected by this method and only call paint().
*/
public void update(Graphics g)
{
- // Tests show that the clearing of the background is only done in
- // two cases:
- // - If the component is lightweight (yes this is in contrast to the spec).
- // or
- // - If the component is a toplevel container.
- if (isLightweight() || getParent() == null)
- {
- Rectangle clip = g.getClipBounds();
- if (clip == null)
- g.clearRect(0, 0, width, height);
- else
- g.clearRect(clip.x, clip.y, clip.width, clip.height);
- }
+ // Note 1: We used to clear the background here for lightweights and
+ // toplevel components. Tests show that this is not what the JDK does
+ // here. Note that there is some special handling and background
+ // clearing code in Container.update(Graphics).
+
+ // Note 2 (for peer implementors): The JDK doesn't seem call update() for
+ // toplevel components, even when an UPDATE event is sent (as a result
+ // of repaint).
paint(g);
}
@@ -2066,11 +2292,46 @@ public abstract class Component
*/
public void repaint(long tm, int x, int y, int width, int height)
{
- if (isShowing())
+ // The repaint() call has previously been delegated to
+ // {@link ComponentPeer.repaint()}. Testing on the JDK using some
+ // dummy peers show that this methods is never called. I think it makes
+ // sense to actually perform the tasks below here, since it's pretty
+ // much peer independent anyway, and makes sure only heavyweights are
+ // bothered by this.
+ ComponentPeer p = peer;
+
+ // 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)
{
- ComponentPeer p = peer;
- if (p != null)
- p.repaint(tm, x, y, width, height);
+ 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 == null ? null : par.peer;
+ }
+
+ // Now send an UPDATE event to the heavyweight component that we've found.
+ if (par != null && par.isVisible() && p != null && pw > 0 && ph > 0)
+ {
+ assert ! (p instanceof LightweightPeer);
+ PaintEvent pe = new PaintEvent(par, PaintEvent.UPDATE,
+ new Rectangle(px, py, pw, ph));
+ getToolkit().getSystemEventQueue().postEvent(pe);
}
}
@@ -2089,10 +2350,7 @@ public abstract class Component
}
/**
- * Prints this component, including all sub-components. This method is
- * provided so that printing can be done in a different manner from
- * painting. However, the implementation in this class simply calls the
- * <code>paintAll()</code> method.
+ * Prints this component, including all sub-components.
*
* @param g the graphics context of the print device
*
@@ -2100,7 +2358,9 @@ public abstract class Component
*/
public void printAll(Graphics g)
{
- paintAll(g);
+ if( peer != null )
+ peer.print( g );
+ paintAll( g );
}
/**
@@ -2159,11 +2419,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;
}
/**
@@ -2179,10 +2450,16 @@ 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;
+ }
+
+ returnValue = p.createImage(width, height);
}
return returnValue;
}
@@ -2198,9 +2475,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;
}
/**
@@ -2219,9 +2506,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;
}
/**
@@ -2251,10 +2548,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;
}
/**
@@ -2288,9 +2596,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;
}
/**
@@ -2592,6 +2912,14 @@ public abstract class Component
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())
+ {
+ numHierarchyListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, 1);
+ }
}
/**
@@ -2607,6 +2935,15 @@ public abstract class Component
public synchronized void removeHierarchyListener(HierarchyListener listener)
{
hierarchyListener = AWTEventMulticaster.remove(hierarchyListener, listener);
+
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyListeners--;
+ if (parent != null)
+ parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
+ -1);
+ }
}
/**
@@ -2642,6 +2979,16 @@ public abstract class Component
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())
+ {
+ numHierarchyBoundsListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ 1);
+ }
}
/**
@@ -2659,6 +3006,16 @@ public abstract class Component
{
hierarchyBoundsListener =
AWTEventMulticaster.remove(hierarchyBoundsListener, listener);
+
+ // 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);
+ }
}
/**
@@ -2677,6 +3034,40 @@ public abstract class Component
}
/**
+ * Fires a HierarchyEvent or HierarchyChangeEvent on this component.
+ *
+ * @param id the event id
+ * @param changed the changed component
+ * @param parent the parent
+ * @param flags the event flags
+ */
+ void fireHierarchyEvent(int id, Component changed, Container parent,
+ long flags)
+ {
+ boolean enabled = false;
+ switch (id)
+ {
+ case HierarchyEvent.HIERARCHY_CHANGED:
+ enabled = hierarchyListener != null
+ || (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0;
+ break;
+ case HierarchyEvent.ANCESTOR_MOVED:
+ case HierarchyEvent.ANCESTOR_RESIZED:
+ enabled = hierarchyBoundsListener != null
+ || (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0;
+ break;
+ default:
+ assert false : "Should not reach here";
+ }
+ if (enabled)
+ {
+ HierarchyEvent ev = new HierarchyEvent(this, id, changed, parent,
+ flags);
+ dispatchEvent(ev);
+ }
+ }
+
+ /**
* Adds the specified listener to this component. This is harmless if the
* listener is null, but if the listener has already been registered, it
* will now be registered twice.
@@ -3010,18 +3401,48 @@ 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);
+
+ // 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);
+
}
/**
@@ -3034,8 +3455,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);
+
}
/**
@@ -3578,18 +4039,31 @@ public abstract class Component
*/
public void addNotify()
{
- if (peer == null)
- peer = getToolkit().createComponent(this);
- else if (parent != null && parent.isLightweight())
- new HeavyweightInLightweightListener(parent);
- /* Now that all the children has gotten their peers, we should
+ // We need to lock the tree here to avoid races and inconsistencies.
+ synchronized (getTreeLock())
+ {
+ if (peer == null)
+ 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. */
- peer.setEventMask(eventMask);
- /* We do not invalidate here, but rather leave that job up to
+ 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);
+
+ // Notify hierarchy listeners.
+ long flags = HierarchyEvent.DISPLAYABILITY_CHANGED;
+ if (isHierarchyVisible())
+ flags |= HierarchyEvent.SHOWING_CHANGED;
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent,
+ flags);
+ }
}
/**
@@ -3603,17 +4077,28 @@ public abstract class Component
*/
public void removeNotify()
{
- // We null our peer field before disposing of it, such that if we're
- // not the event dispatch thread and the dispatch thread is awoken by
- // the dispose call, there will be no race checking the peer's null
- // status.
-
- ComponentPeer tmp = peer;
- peer = null;
- if (tmp != null)
+ // We need to lock the tree here to avoid races and inconsistencies.
+ synchronized (getTreeLock())
{
- tmp.hide();
- tmp.dispose();
+ // We null our peer field before disposing of it, such that if we're
+ // not the event dispatch thread and the dispatch thread is awoken by
+ // the dispose call, there will be no race checking the peer's null
+ // status.
+
+ ComponentPeer tmp = peer;
+ peer = 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);
}
}
@@ -3934,56 +4419,7 @@ public abstract class Component
*/
public void requestFocus ()
{
- if (isDisplayable ()
- && isShowing ()
- && isFocusable ())
- {
- synchronized (getTreeLock ())
- {
- // Find this Component's top-level ancestor.
- Container parent = (this instanceof Container) ? (Container) this
- : getParent();
- while (parent != null
- && !(parent instanceof Window))
- parent = parent.getParent ();
-
- if (parent == null)
- return;
-
- Window toplevel = (Window) parent;
- if (toplevel.isFocusableWindow ())
- {
- if (peer != null && !isLightweight())
- // This call will cause a FOCUS_GAINED event to be
- // posted to the system event queue if the native
- // windowing system grants the focus request.
- peer.requestFocus ();
- else
- {
- // Either our peer hasn't been created yet or we're a
- // lightweight component. In either case we want to
- // post a FOCUS_GAINED event.
- EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
- synchronized (eq)
- {
- KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
- Component currentFocusOwner = manager.getGlobalPermanentFocusOwner ();
- if (currentFocusOwner != null)
- {
- eq.postEvent (new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
- false, this));
- eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, false,
- currentFocusOwner));
- }
- else
- eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, false));
- }
- }
- }
- else
- pendingFocusRequest = new FocusEvent(this, FocusEvent.FOCUS_GAINED);
- }
- }
+ requestFocusImpl(false, true);
}
/**
@@ -4023,61 +4459,7 @@ public abstract class Component
*/
protected boolean requestFocus (boolean temporary)
{
- if (isDisplayable ()
- && isShowing ()
- && isFocusable ())
- {
- synchronized (getTreeLock ())
- {
- // Find this Component's top-level ancestor.
- Container parent = getParent ();
-
- while (parent != null
- && !(parent instanceof Window))
- parent = parent.getParent ();
-
- Window toplevel = (Window) parent;
- if (toplevel.isFocusableWindow ())
- {
- if (peer != null && !isLightweight())
- // This call will cause a FOCUS_GAINED event to be
- // posted to the system event queue if the native
- // windowing system grants the focus request.
- peer.requestFocus ();
- else
- {
- // Either our peer hasn't been created yet or we're a
- // lightweight component. In either case we want to
- // post a FOCUS_GAINED event.
- EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
- synchronized (eq)
- {
- KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
- Component currentFocusOwner = manager.getGlobalPermanentFocusOwner ();
- if (currentFocusOwner != null)
- {
- eq.postEvent (new FocusEvent(currentFocusOwner,
- FocusEvent.FOCUS_LOST,
- temporary, this));
- eq.postEvent (new FocusEvent(this,
- FocusEvent.FOCUS_GAINED,
- temporary,
- currentFocusOwner));
- }
- else
- eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary));
- }
- }
- }
- else
- // FIXME: need to add a focus listener to our top-level
- // ancestor, so that we can post this event when it becomes
- // the focused window.
- pendingFocusRequest = new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary);
- }
- }
- // Always return true.
- return true;
+ return requestFocusImpl(temporary, true);
}
/**
@@ -4105,7 +4487,7 @@ public abstract class Component
*/
public boolean requestFocusInWindow ()
{
- return requestFocusInWindow (false);
+ return requestFocusImpl(false, false);
}
/**
@@ -4136,65 +4518,84 @@ public abstract class Component
*/
protected boolean requestFocusInWindow (boolean temporary)
{
- KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
-
- Window focusedWindow = manager.getFocusedWindow ();
+ return requestFocusImpl(temporary, false);
+ }
- if (isDisplayable ()
- && isShowing ()
- && isFocusable ())
+ /**
+ * Helper method for all 4 requestFocus variants.
+ *
+ * @param temporary indicates if the focus change is temporary
+ * @param focusWindow indicates if the window focus may be changed
+ *
+ * @return <code>false</code> if the request has been definitely denied,
+ * <code>true</code> otherwise
+ */
+ private boolean requestFocusImpl(boolean temporary, boolean focusWindow)
+ {
+ boolean retval = false;
+
+ // Don't try to focus non-focusable and non-visible components.
+ if (isFocusable() && isVisible())
{
- if (focusedWindow != null)
+ ComponentPeer myPeer = peer;
+ if (peer != null)
{
- synchronized (getTreeLock ())
+ // Find Window ancestor and find out if we're showing while
+ // doing this.
+ boolean showing = true;
+ Component window = this;
+ while (! (window instanceof Window))
{
- Container parent = getParent ();
-
- while (parent != null
- && !(parent instanceof Window))
- parent = parent.getParent ();
-
- Window toplevel = (Window) parent;
-
- // Check if top-level ancestor is currently focused window.
- if (focusedWindow == toplevel)
+ if (! window.isVisible())
+ showing = false;
+ window = window.parent;
+ }
+ // Don't allow focus when there is no window or the window
+ // is not focusable.
+ if (window != null && ((Window) window).isFocusableWindow()
+ && showing)
+ {
+ // Search for nearest heavy ancestor (including this
+ // component).
+ Component heavyweightParent = this;
+ while (heavyweightParent.peer instanceof LightweightPeer)
+ heavyweightParent = heavyweightParent.parent;
+
+ // Don't allow focus on lightweight components without
+ // visible heavyweight ancestor
+ if (heavyweightParent != null && heavyweightParent.isVisible())
{
- if (peer != null
- && !isLightweight()
- && !(this instanceof Window))
- // This call will cause a FOCUS_GAINED event to be
- // posted to the system event queue if the native
- // windowing system grants the focus request.
- peer.requestFocus ();
- else
+ // Don't allow focus when heavyweightParent has no peer.
+ myPeer = heavyweightParent.peer;
+ if (myPeer != null)
{
- // Either our peer hasn't been created yet or we're a
- // lightweight component. In either case we want to
- // post a FOCUS_GAINED event.
- EventQueue eq = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
- synchronized (eq)
+ // Register lightweight focus request.
+ if (heavyweightParent != this)
{
- Component currentFocusOwner = manager.getGlobalPermanentFocusOwner ();
- if (currentFocusOwner != null)
- {
- eq.postEvent (new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
- temporary, this));
- eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary,
- currentFocusOwner));
- }
- else
- eq.postEvent (new FocusEvent(this, FocusEvent.FOCUS_GAINED, temporary));
+ KeyboardFocusManager
+ .addLightweightFocusRequest(heavyweightParent,
+ this);
}
+
+ // Try to focus the component.
+ long time = EventQueue.getMostRecentEventTime();
+ boolean success = myPeer.requestFocus(this, temporary,
+ focusWindow,
+ time);
+ if (! success)
+ {
+ // Dequeue key events if focus request failed.
+ KeyboardFocusManager kfm =
+ KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ kfm.dequeueKeyEvents(time, this);
+ }
+ retval = success;
}
}
- else
- return false;
}
}
-
- return true;
}
- return false;
+ return retval;
}
/**
@@ -5186,52 +5587,26 @@ p * <li>the set of backward traversal keys
void dispatchEventImpl(AWTEvent e)
{
- // This boolean tells us not to process focus events when the focus
- // opposite component is the same as the focus component.
- boolean ignoreFocus =
- (e instanceof FocusEvent &&
- ((FocusEvent)e).getComponent() == ((FocusEvent)e).getOppositeComponent());
-
- if (eventTypeEnabled (e.id))
+ // Retarget focus events before dispatching it to the KeyboardFocusManager
+ // in order to handle lightweight components properly.
+ boolean dispatched = false;
+ if (! e.isFocusManagerEvent)
{
- if (e.id != PaintEvent.PAINT && e.id != PaintEvent.UPDATE
- && !ignoreFocus)
- processEvent(e);
-
- // the trick we use to communicate between dispatch and redispatch
- // is to have KeyboardFocusManager.redispatch synchronize on the
- // object itself. we then do not redispatch to KeyboardFocusManager
- // if we are already holding the lock.
- if (! Thread.holdsLock(e))
+ e = KeyboardFocusManager.retargetFocusEvent(e);
+ dispatched = KeyboardFocusManager.getCurrentKeyboardFocusManager()
+ .dispatchEvent(e);
+ }
+
+ if (! dispatched)
+ {
+ if (eventTypeEnabled (e.id))
{
- switch (e.id)
- {
- case WindowEvent.WINDOW_GAINED_FOCUS:
- case WindowEvent.WINDOW_LOST_FOCUS:
- case KeyEvent.KEY_PRESSED:
- case KeyEvent.KEY_RELEASED:
- case KeyEvent.KEY_TYPED:
- case FocusEvent.FOCUS_GAINED:
- case FocusEvent.FOCUS_LOST:
- if (KeyboardFocusManager
- .getCurrentKeyboardFocusManager()
- .dispatchEvent(e))
- return;
- case MouseEvent.MOUSE_PRESSED:
- // A mouse click on an enabled lightweight component
- // which has not yet been marked as consumed by any
- // other mouse listener results in a focus traversal
- // to that component.
- if (isLightweight()
- && isEnabled() && !e.isConsumed())
- requestFocus();
- break;
- }
+ if (e.id != PaintEvent.PAINT && e.id != PaintEvent.UPDATE)
+ processEvent(e);
}
+ if (peer != null)
+ peer.handleEvent(e);
}
-
- if (peer != null)
- peer.handleEvent(e);
}
/**
@@ -5301,6 +5676,26 @@ p * <li>the set of backward traversal keys
}
/**
+ * Returns <code>true</code> when this component and all of its ancestors
+ * are visible, <code>false</code> otherwise.
+ *
+ * @return <code>true</code> when this component and all of its ancestors
+ * are visible, <code>false</code> otherwise
+ */
+ boolean isHierarchyVisible()
+ {
+ boolean visible = isVisible();
+ Component comp = parent;
+ while (comp != null && visible)
+ {
+ comp = comp.parent;
+ if (comp != null)
+ visible = visible && comp.isVisible();
+ }
+ return visible;
+ }
+
+ /**
* 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
diff --git a/java/awt/Container.java b/java/awt/Container.java
index 1ff1b8187..8f508aa76 100644
--- a/java/awt/Container.java
+++ b/java/awt/Container.java
@@ -42,6 +42,7 @@ 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.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
@@ -88,14 +89,16 @@ public class Container extends Component
Dimension maxSize;
/**
- * Keeps track if the Container was cleared during a paint/update.
+ * @since 1.4
*/
- private boolean backCleared;
+ boolean focusCycleRoot;
/**
- * @since 1.4
+ * Indicates if this container provides a focus traversal policy.
+ *
+ * @since 1.5
*/
- boolean focusCycleRoot;
+ private boolean focusTraversalPolicyProvider;
int containerSerializedDataVersion;
@@ -205,10 +208,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;
}
/**
@@ -362,6 +367,16 @@ public class Container extends Component
++ncomponents;
}
+ // Update the counter for Hierarchy(Bounds)Listeners.
+ int childHierarchyListeners = comp.numHierarchyListeners;
+ if (childHierarchyListeners > 0)
+ updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
+ childHierarchyListeners);
+ int childHierarchyBoundsListeners = comp.numHierarchyBoundsListeners;
+ if (childHierarchyBoundsListeners > 0)
+ updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ childHierarchyListeners);
+
// Notify the layout manager.
if (layoutMgr != null)
{
@@ -388,6 +403,10 @@ public class Container extends Component
ContainerListener[] listeners = getContainerListeners();
for (int i = 0; i < listeners.length; i++)
listeners[i].componentAdded(ce);
+
+ // Notify hierarchy listeners.
+ comp.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, comp,
+ this, HierarchyEvent.PARENT_CHANGED);
}
}
@@ -412,6 +431,16 @@ public class Container extends Component
ncomponents - index - 1);
component[--ncomponents] = null;
+ // 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);
+
invalidate();
if (layoutMgr != null)
@@ -423,10 +452,14 @@ public class Container extends Component
{
// Post event to notify of removing the component.
ContainerEvent ce = new ContainerEvent(this,
- ContainerEvent.COMPONENT_REMOVED,
- r);
+ ContainerEvent.COMPONENT_REMOVED,
+ r);
getToolkit().getSystemEventQueue().postEvent(ce);
}
+
+ // Notify hierarchy listeners.
+ r.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r,
+ this, HierarchyEvent.PARENT_CHANGED);
}
}
@@ -475,26 +508,43 @@ public class Container extends Component
r.removeNotify();
+ // 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);
+
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);
}
- }
-
+
+ // Send HierarchyEvent if necessary.
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, this,
+ HierarchyEvent.PARENT_CHANGED);
+
+ }
+
+ if (valid)
invalidate();
- ncomponents = 0;
+ ncomponents = 0;
}
}
@@ -573,19 +623,22 @@ public class Container extends Component
*/
void invalidateTree()
{
- super.invalidate(); // Clean cached layout state.
- for (int i = 0; i < ncomponents; i++)
+ synchronized (getTreeLock())
{
- Component comp = component[i];
- comp.invalidate();
- if (comp instanceof Container)
- ((Container) comp).invalidateTree();
- }
+ 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();
+ }
- if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
- {
- LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
- lm2.invalidateLayout(this);
+ if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
+ {
+ LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
+ lm2.invalidateLayout(this);
+ }
}
}
@@ -672,21 +725,25 @@ public class Container extends Component
*/
public Dimension preferredSize()
{
- synchronized(treeLock)
- {
- if(valid && prefSize != null)
- return new Dimension(prefSize);
- LayoutManager layout = getLayout();
- if (layout != null)
+ Dimension size = prefSize;
+ // Try to return cached value if possible.
+ if (size == null || !(prefSizeSet || valid))
+ {
+ // Need to lock here.
+ synchronized (getTreeLock())
{
- Dimension layoutSize = layout.preferredLayoutSize(this);
- if(valid)
- prefSize = layoutSize;
- return new Dimension(layoutSize);
+ LayoutManager l = layoutMgr;
+ if (l != null)
+ prefSize = l.preferredLayoutSize(this);
+ else
+ prefSize = super.preferredSizeImpl();
+ size = prefSize;
}
- else
- return super.preferredSize ();
}
+ if (size != null)
+ return new Dimension(size);
+ else
+ return size;
}
/**
@@ -708,17 +765,25 @@ public class Container extends Component
*/
public Dimension minimumSize()
{
- if(valid && minSize != null)
- return new Dimension(minSize);
-
- LayoutManager layout = getLayout();
- if (layout != null)
+ Dimension size = minSize;
+ // Try to return cached value if possible.
+ if (size == null || !(minSizeSet || valid))
{
- minSize = layout.minimumLayoutSize (this);
- return minSize;
- }
+ // Need to lock here.
+ synchronized (getTreeLock())
+ {
+ LayoutManager l = layoutMgr;
+ if (l != null)
+ minSize = l.minimumLayoutSize(this);
+ else
+ minSize = super.minimumSizeImpl();
+ size = minSize;
+ }
+ }
+ if (size != null)
+ return new Dimension(size);
else
- return super.minimumSize ();
+ return size;
}
/**
@@ -728,18 +793,25 @@ public class Container extends Component
*/
public Dimension getMaximumSize()
{
- if (valid && maxSize != null)
- return new Dimension(maxSize);
-
- LayoutManager layout = getLayout();
- if (layout != null && layout instanceof LayoutManager2)
+ Dimension size = maxSize;
+ // Try to return cached value if possible.
+ if (size == null || !(maxSizeSet || valid))
{
- LayoutManager2 lm2 = (LayoutManager2) layout;
- maxSize = lm2.maximumLayoutSize(this);
- return maxSize;
+ // Need to lock here.
+ synchronized (getTreeLock())
+ {
+ LayoutManager l = layoutMgr;
+ if (l instanceof LayoutManager2)
+ maxSize = ((LayoutManager2) l).maximumLayoutSize(this);
+ else
+ maxSize = super.maximumSizeImpl();
+ size = maxSize;
+ }
}
+ if (size != null)
+ return new Dimension(size);
else
- return super.getMaximumSize();
+ return size;
}
/**
@@ -755,8 +827,11 @@ public class Container extends Component
float alignmentX = 0.0F;
if (layout != null && layout instanceof LayoutManager2)
{
- LayoutManager2 lm2 = (LayoutManager2) layout;
- alignmentX = lm2.getLayoutAlignmentX(this);
+ synchronized (getTreeLock())
+ {
+ LayoutManager2 lm2 = (LayoutManager2) layout;
+ alignmentX = lm2.getLayoutAlignmentX(this);
+ }
}
else
alignmentX = super.getAlignmentX();
@@ -776,8 +851,11 @@ public class Container extends Component
float alignmentY = 0.0F;
if (layout != null && layout instanceof LayoutManager2)
{
- LayoutManager2 lm2 = (LayoutManager2) layout;
- alignmentY = lm2.getLayoutAlignmentY(this);
+ synchronized (getTreeLock())
+ {
+ LayoutManager2 lm2 = (LayoutManager2) layout;
+ alignmentY = lm2.getLayoutAlignmentY(this);
+ }
}
else
alignmentY = super.getAlignmentY();
@@ -795,13 +873,10 @@ public class Container extends Component
*/
public void paint(Graphics g)
{
- if (!isShowing())
- return;
-
- // Visit heavyweights if the background was cleared
- // for this container.
- visitChildren(g, GfxPaintVisitor.INSTANCE, !backCleared);
- backCleared = false;
+ if (isShowing())
+ {
+ visitChildren(g, GfxPaintVisitor.INSTANCE, true);
+ }
}
/**
@@ -831,14 +906,15 @@ public class Container extends Component
// that overrides isLightweight() to return false, the background is
// also not cleared. So we do a check on !(peer instanceof LightweightPeer)
// instead.
- ComponentPeer p = peer;
- if (p != null && ! (p instanceof LightweightPeer))
+ if (isShowing())
{
- g.clearRect(0, 0, getWidth(), getHeight());
- backCleared = true;
+ ComponentPeer p = peer;
+ if (! (p instanceof LightweightPeer))
+ {
+ g.clearRect(0, 0, getWidth(), getHeight());
+ }
+ paint(g);
}
-
- paint(g);
}
/**
@@ -1174,8 +1250,11 @@ public class Container extends Component
*/
public void addNotify()
{
- super.addNotify();
- addNotifyContainerChildren();
+ synchronized (getTreeLock())
+ {
+ super.addNotify();
+ addNotifyContainerChildren();
+ }
}
/**
@@ -1550,6 +1629,42 @@ public class Container extends Component
}
/**
+ * Set to <code>true</code> if this container provides a focus traversal
+ * policy, <code>false</code> when the root container's focus
+ * traversal policy should be used.
+ *
+ * @return <code>true</code> if this container provides a focus traversal
+ * policy, <code>false</code> when the root container's focus
+ * traversal policy should be used
+ *
+ * @see #setFocusTraversalPolicyProvider(boolean)
+ *
+ * @since 1.5
+ */
+ public final boolean isFocusTraversalPolicyProvider()
+ {
+ return focusTraversalPolicyProvider;
+ }
+
+ /**
+ * Set to <code>true</code> if this container provides a focus traversal
+ * policy, <code>false</code> when the root container's focus
+ * traversal policy should be used.
+ *
+ * @param b <code>true</code> if this container provides a focus traversal
+ * policy, <code>false</code> when the root container's focus
+ * traversal policy should be used
+ *
+ * @see #isFocusTraversalPolicyProvider()
+ *
+ * @since 1.5
+ */
+ public final void setFocusTraversalPolicyProvider(boolean b)
+ {
+ focusTraversalPolicyProvider = b;
+ }
+
+ /**
* Check whether this Container is a focus cycle root.
*
* @return true if this is a focus cycle root, false otherwise
@@ -1656,24 +1771,27 @@ public class Container extends Component
if (comp == this)
throw new IllegalArgumentException("cannot add component to itself");
- // FIXME: Implement reparenting.
- if ( comp.getParent() != this)
- throw new AssertionError("Reparenting is not implemented yet");
- else
+ synchronized (getTreeLock())
{
- // Find current component index.
- int currentIndex = getComponentZOrder(comp);
- if (currentIndex < index)
- {
- System.arraycopy(component, currentIndex + 1, component,
- currentIndex, index - currentIndex);
- }
+ // FIXME: Implement reparenting.
+ if ( comp.getParent() != this)
+ throw new AssertionError("Reparenting is not implemented yet");
else
{
- System.arraycopy(component, index, component, index + 1,
- currentIndex - index);
+ // Find current component index.
+ int currentIndex = getComponentZOrder(comp);
+ if (currentIndex < index)
+ {
+ System.arraycopy(component, currentIndex + 1, component,
+ currentIndex, index - currentIndex);
+ }
+ else
+ {
+ System.arraycopy(component, index, component, index + 1,
+ currentIndex - index);
+ }
+ component[index] = comp;
}
- component[index] = comp;
}
}
@@ -1692,19 +1810,22 @@ public class Container extends Component
*/
public final int getComponentZOrder(Component comp)
{
- int index = -1;
- if (component != null)
+ synchronized (getTreeLock())
{
- for (int i = 0; i < ncomponents; i++)
+ int index = -1;
+ if (component != null)
{
- if (component[i] == comp)
+ for (int i = 0; i < ncomponents; i++)
{
- index = i;
- break;
+ if (component[i] == comp)
+ {
+ index = i;
+ break;
+ }
}
}
+ return index;
}
- return index;
}
// Hidden helper methods.
@@ -1860,6 +1981,85 @@ public class Container extends Component
}
}
+ /**
+ * Fires hierarchy events to the children of this container and this
+ * container itself. This overrides {@link Component#fireHierarchyEvent}
+ * in order to forward this event to all children.
+ */
+ void fireHierarchyEvent(int id, Component changed, Container parent,
+ long flags)
+ {
+ // Only propagate event if there is actually a listener waiting for it.
+ if ((id == HierarchyEvent.HIERARCHY_CHANGED && numHierarchyListeners > 0)
+ || ((id == HierarchyEvent.ANCESTOR_MOVED
+ || id == HierarchyEvent.ANCESTOR_RESIZED)
+ && numHierarchyBoundsListeners > 0))
+ {
+ for (int i = 0; i < ncomponents; i++)
+ component[i].fireHierarchyEvent(id, changed, parent, flags);
+ super.fireHierarchyEvent(id, changed, parent, flags);
+ }
+ }
+
+ /**
+ * Adjusts the number of hierarchy listeners of this container and all of
+ * its parents. This is called by the add/remove listener methods and
+ * structure changing methods in Container.
+ *
+ * @param type the type, either {@link AWTEvent#HIERARCHY_BOUNDS_EVENT_MASK}
+ * or {@link AWTEvent#HIERARCHY_EVENT_MASK}
+ * @param delta the number of listeners added or removed
+ */
+ void updateHierarchyListenerCount(long type, int delta)
+ {
+ if (type == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)
+ numHierarchyBoundsListeners += delta;
+ else if (type == AWTEvent.HIERARCHY_EVENT_MASK)
+ numHierarchyListeners += delta;
+ else
+ assert false : "Should not reach here";
+
+ if (parent != null)
+ 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 ())
diff --git a/java/awt/ContainerOrderFocusTraversalPolicy.java b/java/awt/ContainerOrderFocusTraversalPolicy.java
index 23b4ac2e8..14afd3648 100644
--- a/java/awt/ContainerOrderFocusTraversalPolicy.java
+++ b/java/awt/ContainerOrderFocusTraversalPolicy.java
@@ -346,28 +346,30 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy
|| !root.isDisplayable ())
return null;
- if (root.visible && root.isDisplayable() && root.enabled
- && root.focusable)
+ if (accept(root))
return root;
- Component[] componentArray = root.getComponents ();
-
- for (int i = 0; i < componentArray.length; i++)
+ int ncomponents = root.getComponentCount();
+ for (int i = 0; i < ncomponents; i++)
{
- Component component = componentArray [i];
-
- if (component.visible && component.isDisplayable() && component.enabled
- && component.focusable)
- return component;
-
- if (component instanceof Container)
+ Component component = root.getComponent(i);
+ if (component instanceof Container
+ && !((Container) component).isFocusCycleRoot())
{
- Component result = getFirstComponent ((Container) component);
-
- if (result != null
- && (result.visible && result.isDisplayable() && result.enabled && result.focusable))
- return result;
+ Component first = null;
+ Container cont = (Container) component;
+ if (cont.isFocusTraversalPolicyProvider())
+ {
+ FocusTraversalPolicy childPol = cont.getFocusTraversalPolicy();
+ first = childPol.getFirstComponent(cont);
+ }
+ else
+ first = getFirstComponent(cont);
+ if (first != null)
+ return first;
}
+ else if (accept(component))
+ return component;
}
return null;
diff --git a/java/awt/Cursor.java b/java/awt/Cursor.java
index 0ff987cd9..4d339b721 100644
--- a/java/awt/Cursor.java
+++ b/java/awt/Cursor.java
@@ -116,6 +116,16 @@ public class Cursor implements java.io.Serializable
*/
public static final int MOVE_CURSOR = 13;
+ private static String[] NAMES = { "Default Cursor", "Crosshair Cursor",
+ "Text Cursor", "Wait Cursor",
+ "Southwest Resize Cursor",
+ "Southeast Resize Cursor",
+ "Northwest Resize Cursor",
+ "Northeast Resize Cursor",
+ "North Resize Cursor", "South Resize Cursor",
+ "West Resize Cursor", "East Resize Cursor",
+ "Hand Cursor", "Move Cursor" };
+
public static final int CUSTOM_CURSOR = 0xFFFFFFFF;
private static final int PREDEFINED_COUNT = 14;
@@ -142,7 +152,10 @@ public class Cursor implements java.io.Serializable
throw new IllegalArgumentException ("invalid cursor " + type);
this.type = type;
- // FIXME: lookup and set name?
+
+ name = NAMES[type];
+
+ // FIXME: lookup?
}
/** This constructor is used internally only.
diff --git a/java/awt/DefaultKeyboardFocusManager.java b/java/awt/DefaultKeyboardFocusManager.java
index 037cb834c..9fea99b78 100644
--- a/java/awt/DefaultKeyboardFocusManager.java
+++ b/java/awt/DefaultKeyboardFocusManager.java
@@ -163,7 +163,13 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager
if (e.id == WindowEvent.WINDOW_ACTIVATED)
setGlobalActiveWindow (target);
else if (e.id == WindowEvent.WINDOW_GAINED_FOCUS)
- setGlobalFocusedWindow (target);
+ {
+ setGlobalFocusedWindow (target);
+ FocusTraversalPolicy p = target.getFocusTraversalPolicy();
+ Component toFocus = p.getInitialComponent(target);
+ if (toFocus != null)
+ toFocus.requestFocusInWindow();
+ }
else if (e.id != WindowEvent.WINDOW_LOST_FOCUS
&& e.id != WindowEvent.WINDOW_DEACTIVATED)
return false;
@@ -173,51 +179,18 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager
}
else if (e instanceof FocusEvent)
{
- Component target = (Component) e.getSource ();
+ FocusEvent fe = (FocusEvent) e;
+ Component target = fe.getComponent ();
+ boolean retval = false;
if (e.id == FocusEvent.FOCUS_GAINED)
{
- if (! (target instanceof Window))
- {
- if (((FocusEvent) e).isTemporary ())
- setGlobalFocusOwner (target);
- else
- setGlobalPermanentFocusOwner (target);
- }
-
- // Keep track of this window's focus owner.
-
- // Find the target Component's top-level ancestor. target
- // may be a window.
- Container parent = target.getParent ();
-
- while (parent != null
- && !(parent instanceof Window))
- parent = parent.getParent ();
-
- // If the parent is null and target is not a window, then target is an
- // unanchored component and so we don't want to set the focus owner.
- if (! (parent == null && ! (target instanceof Window)))
- {
- Window toplevel = parent == null ?
- (Window) target : (Window) parent;
-
- Component focusOwner = getFocusOwner ();
- if (focusOwner != null
- && ! (focusOwner instanceof Window))
- toplevel.setFocusOwner (focusOwner);
- }
+ retval = handleFocusGained(fe);
}
else if (e.id == FocusEvent.FOCUS_LOST)
{
- if (((FocusEvent) e).isTemporary ())
- setGlobalFocusOwner (null);
- else
- setGlobalPermanentFocusOwner (null);
+ retval = handleFocusLost(fe);
}
-
- redispatchEvent(target, e);
-
return true;
}
else if (e instanceof KeyEvent)
@@ -256,6 +229,95 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager
return false;
}
+ /**
+ * Handles FOCUS_GAINED events in {@link #dispatchEvent(AWTEvent)}.
+ *
+ * @param fe the focus event
+ */
+ private boolean handleFocusGained(FocusEvent fe)
+ {
+ Component target = fe.getComponent ();
+
+ // If old focus owner != new focus owner, notify old focus
+ // owner that it has lost focus.
+ Component oldFocusOwner = getGlobalFocusOwner();
+ if (oldFocusOwner != null && oldFocusOwner != target)
+ {
+ FocusEvent lost = new FocusEvent(oldFocusOwner,
+ FocusEvent.FOCUS_LOST,
+ fe.isTemporary(), target);
+ oldFocusOwner.dispatchEvent(lost);
+ }
+
+ setGlobalFocusOwner (target);
+ if (target != getGlobalFocusOwner())
+ {
+ // Focus transfer was rejected, like when the target is not
+ // focusable.
+ dequeueKeyEvents(-1, target);
+ // FIXME: Restore focus somehow.
+ }
+ else
+ {
+ if (! fe.isTemporary())
+ {
+ setGlobalPermanentFocusOwner (target);
+ if (target != getGlobalPermanentFocusOwner())
+ {
+ // Focus transfer was rejected, like when the target is not
+ // focusable.
+ dequeueKeyEvents(-1, target);
+ // FIXME: Restore focus somehow.
+ }
+ else
+ {
+ redispatchEvent(target, fe);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Handles FOCUS_LOST events for {@link #dispatchEvent(AWTEvent)}.
+ *
+ * @param fe the focus event
+ *
+ * @return if the event has been handled
+ */
+ private boolean handleFocusLost(FocusEvent fe)
+ {
+ Component currentFocus = getGlobalFocusOwner();
+ if (currentFocus != fe.getOppositeComponent())
+ {
+ setGlobalFocusOwner(null);
+ if (getGlobalFocusOwner() != null)
+ {
+ // TODO: Is this possible? If so, then we should try to restore
+ // the focus.
+ }
+ else
+ {
+ if (! fe.isTemporary())
+ {
+ setGlobalPermanentFocusOwner(null);
+ if (getGlobalPermanentFocusOwner() != null)
+ {
+ // TODO: Is this possible? If so, then we should try to
+ // restore the focus.
+ }
+ else
+ {
+ fe.setSource(currentFocus);
+ redispatchEvent(currentFocus, fe);
+ }
+ }
+ }
+ }
+ return true;
+ }
+
private boolean enqueueKeyEvent (KeyEvent e)
{
Iterator i = delayRequests.iterator ();
diff --git a/java/awt/EventDispatchThread.java b/java/awt/EventDispatchThread.java
index 7cb8af831..074a84975 100644
--- a/java/awt/EventDispatchThread.java
+++ b/java/awt/EventDispatchThread.java
@@ -82,17 +82,7 @@ class EventDispatchThread extends Thread
try
{
AWTEvent evt = queue.getNextEvent();
-
- KeyboardFocusManager manager;
- manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
-
- // Try to dispatch this event to the current keyboard focus
- // manager. It will dispatch all FocusEvents, all
- // WindowEvents related to focus, and all KeyEvents,
- // returning true. Otherwise, it returns false and we
- // dispatch the event normally.
- if (!manager.dispatchEvent (evt))
- queue.dispatchEvent(evt);
+ queue.dispatchEvent(evt);
}
catch (ThreadDeath death)
{
diff --git a/java/awt/FlowLayout.java b/java/awt/FlowLayout.java
index 7d0771d91..8c9919528 100644
--- a/java/awt/FlowLayout.java
+++ b/java/awt/FlowLayout.java
@@ -276,26 +276,24 @@ public class FlowLayout implements LayoutManager, Serializable
}
/**
- * Sets the horizontal gap between components to the specified value.
- *
+ * Sets the horizontal gap between lines of components to the specified value.
+ * No Exception is thrown if hgap < 0.
+ *
* @param hgap The new horizontal gap between components.
*/
public void setHgap (int hgap)
{
- if (hgap < 0)
- throw new IllegalArgumentException ("horizontal gap must be nonnegative");
this.hgap = hgap;
}
/**
* Sets the vertical gap between lines of components to the specified value.
+ * No Exception is thrown if vgap < 0.
*
* @param vgap The new vertical gap.
*/
public void setVgap (int vgap)
{
- if (vgap < 0)
- throw new IllegalArgumentException ("vertical gap must be nonnegative");
this.vgap = vgap;
}
diff --git a/java/awt/Font.java b/java/awt/Font.java
index 7e0306dc0..1c22ce7b4 100644
--- a/java/awt/Font.java
+++ b/java/awt/Font.java
@@ -48,6 +48,8 @@ import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.peer.FontPeer;
+import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
@@ -583,6 +585,34 @@ public class Font implements Serializable
}
/**
+ * Creates a new font from a File object.
+ *
+ * @see #layoutGlyphVector(FontRenderContext, char[], int, int, int)
+ *
+ * @param fontFormat - Integer code indicating the format the font data is
+ * in.Currently this can only be {@link #TRUETYPE_FONT}.
+ * @param file - a {@link File} from which font data will be read.
+ *
+ * @return A new {@link Font} of the format indicated.
+ *
+ * @throws IllegalArgumentException if <code>fontType</code> is not
+ * recognized.
+ * @throws NullPointerException if <code>file</code> is <code>null</code>.
+ * @throws FontFormatException if data in the file is invalid or cannot be read..
+ * @throws SecurityException if the caller has no read permission for the file.
+ * @throws IOException if the file cannot be read
+ *
+ * @since 1.5
+ */
+ public static Font createFont (int fontFormat, File file)
+ throws FontFormatException, IOException
+ {
+ if( file == null )
+ throw new NullPointerException("Null file argument");
+ return tk().createFont(fontFormat, new FileInputStream( file ));
+ }
+
+ /**
* Maps characters to glyphs in a one-to-one relationship, returning a new
* {@link GlyphVector} with a mapped glyph for each input character. This
* sort of mapping is often sufficient for some scripts such as Roman, but
diff --git a/java/awt/Graphics2D.java b/java/awt/Graphics2D.java
index b3ecbc58a..ada13edc5 100644
--- a/java/awt/Graphics2D.java
+++ b/java/awt/Graphics2D.java
@@ -53,23 +53,21 @@ import java.util.Map;
/**
* An abstract class defining a device independent two-dimensional vector
* graphics API. Concrete subclasses implement this API for output of
- * vector graphics to: (*)
+ * vector graphics to:
* <p>
* <ul>
* <li>a {@link javax.swing.JComponent} - in the
* {@link javax.swing.JComponent#paint(Graphics)} method, the incoming
* {@link Graphics} should always be an instance of
- * <code>Graphics2D</code> (*);</li>
+ * <code>Graphics2D</code>;</li>
* <li>a {@link BufferedImage} - see
- * {@link BufferedImage#createGraphics()} (*);</li>
+ * {@link BufferedImage#createGraphics()};</li>
* <li>a {@link java.awt.print.PrinterJob} - in the
* {@link Printable#print(Graphics, PageFormat, int)} method, the incoming
- * {@link Graphics} should always be an instance of <code>Graphics2D</code>
- * (*).</li>
+ * {@link Graphics} should always be an instance of
+ * <code>Graphics2D</code>.</li>
* </ul>
* <p>
- * (*) Support for this API is not fully implemented in GNU Classpath yet.
- * <p>
* Third party libraries provide support for output to other formats via this
* API, including encapsulated postscript (EPS), portable document format (PDF),
* and scalable vector graphics (SVG).
diff --git a/java/awt/GridBagLayout.java b/java/awt/GridBagLayout.java
index e4711c71e..d84b7d6df 100644
--- a/java/awt/GridBagLayout.java
+++ b/java/awt/GridBagLayout.java
@@ -1,5 +1,5 @@
/* GridBagLayout - Layout manager for components according to GridBagConstraints
- 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.
@@ -330,117 +330,14 @@ public class GridBagLayout
protected void AdjustForGravity (GridBagConstraints constraints,
Rectangle r)
{
- Rectangle result = new Rectangle (0, 0, 0, 0);
-
- // Calculate width and height.
-
- // Adjust width and height for fill value.
- switch (constraints.fill)
- {
- case GridBagConstraints.NONE:
- result.width = 0;
- result.height = 0;
- break;
- case GridBagConstraints.BOTH:
- result.width = r.width;
- result.height = r.height;
- break;
- case GridBagConstraints.HORIZONTAL:
- result.width = r.width;
- result.height = 0;
- break;
- case GridBagConstraints.VERTICAL:
- result.width = 0;
- result.height = r.height;
- break;
- }
-
- // Adjust width and height for insets, and clamp to minimum
- // values of ipadx and ipady.
- result.width = Math.max(result.width
- - constraints.insets.left
- - constraints.insets.right,
- constraints.ipadx);
- result.height = Math.max(result.height
- - constraints.insets.top
- - constraints.insets.bottom,
- constraints.ipady);
-
- // Calculate x and y.
-
- // Do not account for the internal padding when setting the
- // result rectangle's x and y co-ordinates.
- int rect_width = r.width - constraints.ipadx;
- int rect_height = r.height - constraints.ipady;
-
- int half_width = (rect_width + constraints.insets.left
- - constraints.insets.right) / 2;
- int half_height = (rect_height + constraints.insets.top
- - constraints.insets.bottom) / 2;
-
- // Adjust x and y for anchor value.
- switch (constraints.anchor)
- {
- case GridBagConstraints.CENTER:
- result.x = r.x + half_width;
- result.y = r.y + half_height;
- break;
- case GridBagConstraints.NORTH:
- result.x = r.x + half_width;
- result.y = r.y + constraints.insets.top;
- break;
- case GridBagConstraints.NORTHEAST:
- result.x = r.x + rect_width - constraints.insets.right;
- result.y = r.y + constraints.insets.top;
- break;
- case GridBagConstraints.EAST:
- result.x = r.x + rect_width - constraints.insets.right;
- result.y = r.y + half_height;
- break;
- case GridBagConstraints.SOUTHEAST:
- result.x = r.x + rect_width - constraints.insets.right;
- result.y = r.y + rect_height - constraints.insets.bottom;
- break;
- case GridBagConstraints.SOUTH:
- result.x = r.x + half_width;
- result.y = r.y + rect_height - constraints.insets.bottom;
- break;
- case GridBagConstraints.SOUTHWEST:
- result.x = r.x + constraints.insets.left;
- result.y = r.y + rect_height - constraints.insets.bottom;
- break;
- case GridBagConstraints.WEST:
- result.x = r.x + constraints.insets.left;
- result.y = r.y + half_height;
- break;
- case GridBagConstraints.NORTHWEST:
- result.x = r.x + constraints.insets.left;
- result.y = r.y + constraints.insets.top;
- break;
- }
-
- // Adjust x and y for fill, clamping values to the external
- // padding boundaries where necessary.
- switch (constraints.fill)
- {
- case GridBagConstraints.NONE:
- break;
- case GridBagConstraints.BOTH:
- result.x = r.x + constraints.insets.left;
- result.y = r.y + constraints.insets.top;
- break;
- case GridBagConstraints.HORIZONTAL:
- result.x = r.x + constraints.insets.left;
- break;
- case GridBagConstraints.VERTICAL:
- result.y = r.y + constraints.insets.top;
- break;
- }
-
- r.x = result.x;
- r.y = result.y;
- r.width = result.width;
- r.height = result.height;
+ Insets insets = constraints.insets;
+ if (insets != null)
+ {
+ r.x += insets.left;
+ r.y += insets.top;
+ r.width -= insets.left + insets.right;
+ r.height -= insets.top + insets.bottom;
+ }
}
/**
diff --git a/java/awt/GridLayout.java b/java/awt/GridLayout.java
index 80d964142..a6836681d 100644
--- a/java/awt/GridLayout.java
+++ b/java/awt/GridLayout.java
@@ -254,14 +254,11 @@ public class GridLayout implements LayoutManager, Serializable
this.cols = newCols;
}
- /** Set the horizontal gap
+ /** Set the horizontal gap. An Exception is not thrown if hgap < 0.
* @param hgap The horizontal gap
- * @exception IllegalArgumentException If the hgap value is less than zero.
*/
public void setHgap (int hgap)
{
- if (hgap < 0)
- throw new IllegalArgumentException ("horizontal gap must be nonnegative");
this.hgap = hgap;
}
@@ -280,21 +277,18 @@ public class GridLayout implements LayoutManager, Serializable
this.rows = newRows;
}
- /** Set the vertical gap.
+ /** Set the vertical gap. An Exception is not thrown if vgap < 0.
* @param vgap The vertical gap
- * @exception IllegalArgumentException If the vgap value is less than zero.
*/
public void setVgap (int vgap)
{
- if (vgap < 0)
- throw new IllegalArgumentException ("vertical gap must be nonnegative");
this.vgap = vgap;
}
/** Return String description of this object. */
public String toString ()
{
- return ("[" + getClass ().getName ()
+ return (getClass ().getName () + "["
+ ",hgap=" + hgap + ",vgap=" + vgap
+ ",rows=" + rows + ",cols=" + cols
+ "]");
diff --git a/java/awt/Image.java b/java/awt/Image.java
index 6ade302a1..8a1cc0f00 100644
--- a/java/awt/Image.java
+++ b/java/awt/Image.java
@@ -1,5 +1,5 @@
/* Image.java -- superclass for images
- Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -50,7 +50,7 @@ import java.awt.image.ReplicateScaleFilter;
*
* @author Aaron M. Renn (arenn@urbanophile.com)
* @since 1.0
- * @status updated to 1.4
+ * @status updated to 1.5
*/
public abstract class Image
{
@@ -102,6 +102,12 @@ public abstract class Image
public static final int SCALE_AREA_AVERAGING = 16;
/**
+ * The acceleration priority of the image
+ * @since 1.5
+ */
+ protected float accelerationPriority;
+
+ /**
* A default constructor for subclasses.
*/
public Image()
@@ -205,4 +211,32 @@ public abstract class Image
* includes the actual image data.
*/
public abstract void flush();
+
+ /**
+ * Sets the acceleration priority of the image.
+ * This is a value from 0 (lowest) to 1 (highest), which may
+ * be used as a hint for image acceleration.
+ * E.g. higher priority images may be stored in video memory.
+ * @param priority - the priority
+ * @throws IllegalArgumentException if priority is not >= 0 and <= 1.
+ *
+ * @since 1.5
+ */
+ public void setAccelerationPriority(float priority)
+ {
+ if( priority < 0f || priority > 1f)
+ throw new IllegalArgumentException("Invalid priority value.");
+ accelerationPriority = priority;
+ }
+
+ /**
+ * Returns the acceleration priority of the image.
+ *
+ * @see #setAccelerationPriority(float)
+ * @since 1.5
+ */
+ public float getAccelerationPriority()
+ {
+ return accelerationPriority;
+ }
} // class Image
diff --git a/java/awt/KeyboardFocusManager.java b/java/awt/KeyboardFocusManager.java
index 371ea9bdf..eacbceb7d 100644
--- a/java/awt/KeyboardFocusManager.java
+++ b/java/awt/KeyboardFocusManager.java
@@ -304,10 +304,7 @@ public abstract class KeyboardFocusManager
*/
public Component getFocusOwner ()
{
- Component owner = (Component) getObject (currentFocusOwners);
- if (owner == null)
- owner = (Component) getObject (currentPermanentFocusOwners);
- return owner;
+ return (Component) getObject (currentFocusOwners);
}
/**
@@ -323,10 +320,7 @@ public abstract class KeyboardFocusManager
*/
protected Component getGlobalFocusOwner ()
{
- // Check if there is a temporary focus owner.
- Component focusOwner = (Component) getGlobalObject (currentFocusOwners);
-
- return (focusOwner == null) ? getGlobalPermanentFocusOwner () : focusOwner;
+ return (Component) getGlobalObject(currentFocusOwners, true);
}
/**
@@ -409,7 +403,7 @@ public abstract class KeyboardFocusManager
*/
protected Component getGlobalPermanentFocusOwner ()
{
- return (Component) getGlobalObject (currentPermanentFocusOwners);
+ return (Component) getGlobalObject (currentPermanentFocusOwners, true);
}
/**
@@ -455,7 +449,7 @@ public abstract class KeyboardFocusManager
*/
protected Window getGlobalFocusedWindow ()
{
- return (Window) getGlobalObject (currentFocusedWindows);
+ return (Window) getGlobalObject (currentFocusedWindows, true);
}
/**
@@ -497,7 +491,7 @@ public abstract class KeyboardFocusManager
*/
protected Window getGlobalActiveWindow()
{
- return (Window) getGlobalObject (currentActiveWindows);
+ return (Window) getGlobalObject (currentActiveWindows, true);
}
/**
@@ -663,7 +657,7 @@ public abstract class KeyboardFocusManager
*/
protected Container getGlobalCurrentFocusCycleRoot ()
{
- return (Container) getGlobalObject (currentFocusCycleRoots);
+ return (Container) getGlobalObject (currentFocusCycleRoots, true);
}
/**
@@ -1105,11 +1099,9 @@ public abstract class KeyboardFocusManager
*/
public final void redispatchEvent (Component target, AWTEvent e)
{
- synchronized (e)
- {
- e.setSource (target);
- target.dispatchEvent (e);
- }
+ e.isFocusManagerEvent = true;
+ target.dispatchEvent (e);
+ e.isFocusManagerEvent = false;
}
/**
@@ -1355,17 +1347,19 @@ public abstract class KeyboardFocusManager
* @see #getGlobalActiveWindow()
* @see #getGlobalCurrentFocusCycleRoot()
*/
- private Object getGlobalObject (Map globalMap)
+ private Object getGlobalObject (Map globalMap, boolean checkThread)
{
- ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
- KeyboardFocusManager managerForCallingThread
- = (KeyboardFocusManager) currentKeyboardFocusManagers.get (currentGroup);
-
- if (this != managerForCallingThread)
- throw new SecurityException ("Attempted to retrieve an object from a "
- + "keyboard focus manager that isn't "
- + "associated with the current thread group.");
+ if (checkThread)
+ {
+ ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
+ KeyboardFocusManager managerForCallingThread =
+ (KeyboardFocusManager) currentKeyboardFocusManagers.get(currentGroup);
+ if (this != managerForCallingThread)
+ throw new SecurityException ("Attempted to retrieve an object from a "
+ + "keyboard focus manager that isn't "
+ + "associated with the current thread group.");
+ }
synchronized (globalMap)
{
Collection globalObjects = globalMap.values ();
@@ -1406,7 +1400,7 @@ public abstract class KeyboardFocusManager
synchronized (globalMap)
{
// Save old object.
- Object oldObject = getGlobalObject (globalMap);
+ Object oldObject = getGlobalObject(globalMap, false);
// Nullify old object.
Collection threadGroups = globalMap.keySet ();
@@ -1436,4 +1430,48 @@ public abstract class KeyboardFocusManager
}
}
}
+
+
+ /**
+ * Maps focus requests from heavyweight to lightweight components.
+ */
+ private static HashMap focusRequests = new HashMap();
+
+ /**
+ * Retargets focus events that come from the peer (which only know about
+ * heavyweight components) to go to the correct lightweight component
+ * if appropriate.
+ *
+ * @param ev the event to check
+ *
+ * @return the retargetted event
+ */
+ static AWTEvent retargetFocusEvent(AWTEvent ev)
+ {
+ if (ev instanceof FocusEvent)
+ {
+ FocusEvent fe = (FocusEvent) ev;
+ Component target = fe.getComponent();
+ if (focusRequests.containsKey(target))
+ {
+ Component lightweight = (Component) focusRequests.get(target);
+ ev = new FocusEvent(lightweight, fe.id, fe.isTemporary());
+ focusRequests.remove(target);
+ }
+ }
+ return ev;
+ }
+
+ /**
+ * Adds a lightweight focus request for a heavyweight component.
+ *
+ * @param heavyweight the heavyweight from which we will receive a focus
+ * event soon
+ * @param lightweight the lightweight that ultimately receives the request
+ */
+ static void addLightweightFocusRequest(Component heavyweight,
+ Component lightweight)
+ {
+ focusRequests.put(heavyweight, lightweight);
+ }
}
diff --git a/java/awt/LightweightDispatcher.java b/java/awt/LightweightDispatcher.java
index e777145b0..3ea3f90a6 100644
--- a/java/awt/LightweightDispatcher.java
+++ b/java/awt/LightweightDispatcher.java
@@ -152,8 +152,11 @@ class LightweightDispatcher
target = findTarget(parent, loc);
while (target == null && parent != null)
{
- if (parent.getMouseListeners().length > 0
- || parent.getMouseMotionListeners().length > 0)
+ if (parent.mouseListener != null
+ || parent.mouseMotionListener != null
+ || (parent.eventMask
+ & (AWTEvent.MOUSE_EVENT_MASK
+ | AWTEvent.MOUSE_MOTION_EVENT_MASK)) != 0)
{
target = parent;
}
@@ -175,24 +178,22 @@ class LightweightDispatcher
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 only if
- // there is currently no component from which a drag operation
- // started (dragTarget == null) or the target is that component
- // (dragTarget == target)
- // That way a user can click and hold on a button (putting it into
- // the armed state), move the cursor above other buttons without
- // affecting their rollover state and get back to the initial
- // button.
- if (target != null && (dragTarget == null || dragTarget == target))
+ // 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(),
+ 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);
}
}
@@ -219,7 +220,11 @@ class LightweightDispatcher
// it was released.
if (dragTarget != null && dragButton == ev.getButton())
{
- target = dragTarget;
+ // 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;
}
@@ -297,8 +302,11 @@ class LightweightDispatcher
if (child.isShowing())
{
if (child.contains(loc.x - child.getX(), loc.y - child.getY())
- && (child.getMouseListeners().length > 0
- || child.getMouseMotionListeners().length > 0))
+ && (child.mouseListener != null
+ || child.mouseMotionListener != null
+ || (child.eventMask
+ & (AWTEvent.MOUSE_EVENT_MASK
+ | AWTEvent.MOUSE_MOTION_EVENT_MASK)) != 0))
{
target = child;
break;
diff --git a/java/awt/List.java b/java/awt/List.java
index e6c0ec170..174e5d76b 100644
--- a/java/awt/List.java
+++ b/java/awt/List.java
@@ -66,6 +66,11 @@ public class List extends Component
* 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;
@@ -103,7 +108,7 @@ private int[] selected;
* @serial An index value used by <code>makeVisible()</code> and
* <code>getVisibleIndex</code>.
*/
-private int visibleIndex;
+private int visibleIndex = -1;
// The list of ItemListeners for this object.
private ItemListener item_listeners;
@@ -111,7 +116,6 @@ private ItemListener item_listeners;
// The list of ActionListeners for this object.
private ActionListener action_listeners;
-
/*************************************************************************/
/*
@@ -171,6 +175,7 @@ List(int rows, boolean multipleMode)
if (GraphicsEnvironment.isHeadless())
throw new HeadlessException ();
+
}
/*************************************************************************/
@@ -309,12 +314,13 @@ setMultipleMode(boolean multipleMode)
*/
public void
setMultipleSelections(boolean multipleMode)
-{
+{
this.multipleMode = multipleMode;
ListPeer peer = (ListPeer) getPeer ();
if (peer != null)
peer.setMultipleMode (multipleMode);
+
}
/*************************************************************************/
@@ -514,6 +520,12 @@ add(String item, int index)
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
@@ -538,7 +550,17 @@ addItem(String item, int index)
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)
@@ -575,15 +597,6 @@ remove(int index) throws IllegalArgumentException
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);
@@ -639,6 +652,8 @@ clear()
ListPeer peer = (ListPeer) getPeer ();
if (peer != null)
peer.removeAll ();
+
+ selected = new int[0];
}
/*************************************************************************/
@@ -690,6 +705,7 @@ getSelectedIndex()
if (selected == null || selected.length != 1)
return -1;
+
return selected[0];
}
@@ -708,7 +724,8 @@ getSelectedIndexes()
{
ListPeer l = (ListPeer) peer;
selected = l.getSelectedIndexes ();
- }
+ }
+
return selected;
}
@@ -857,13 +874,38 @@ getVisibleIndex()
*
* @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);
-}
+ 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;
+ }
+ }
/*************************************************************************/
@@ -875,9 +917,26 @@ select(int index)
public synchronized void
deselect(int index)
{
- ListPeer lp = (ListPeer)getPeer();
- if (lp != null)
- lp.deselect(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;
+ }
}
/*************************************************************************/
@@ -1266,4 +1325,19 @@ paramString()
accessibleContext = new AccessibleAWTList();
return accessibleContext;
}
+
+ /**
+ * Generate a unique name for this <code>List</code>.
+ *
+ * @return A unique name for this <code>List</code>.
+ */
+ String generateName()
+ {
+ return "list" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_list_number++;
+ }
} // class List
diff --git a/java/awt/Menu.java b/java/awt/Menu.java
index 6daec72cf..f900d9295 100644
--- a/java/awt/Menu.java
+++ b/java/awt/Menu.java
@@ -58,6 +58,11 @@ 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;
@@ -485,5 +490,20 @@ paramString()
accessibleContext = new AccessibleAWTMenu();
return accessibleContext;
}
+
+ /**
+ * Generate a unique name for this <code>Menu</code>.
+ *
+ * @return A unique name for this <code>Menu</code>.
+ */
+ String generateName()
+ {
+ return "menu" + getUniqueLong();
+ }
+ private static synchronized long getUniqueLong()
+ {
+ return next_menu_number++;
+ }
+
} // class Menu
diff --git a/java/awt/MenuBar.java b/java/awt/MenuBar.java
index 3c6b91564..bd658cde6 100644
--- a/java/awt/MenuBar.java
+++ b/java/awt/MenuBar.java
@@ -60,10 +60,15 @@ public class MenuBar extends MenuComponent
implements MenuContainer, Serializable, Accessible
{
-//Serialization Constant
+ // Serialization Constant
private static final long serialVersionUID = -4930327919388951260L;
/**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_menubar_number;
+
+ /**
* @serial The menu used for providing help information
*/
private Menu helpMenu;
@@ -331,6 +336,21 @@ public class MenuBar extends MenuComponent
accessibleContext = new AccessibleAWTMenuBar();
return accessibleContext;
}
+
+ /**
+ * Generate a unique name for this <code>MenuBar</code>.
+ *
+ * @return A unique name for this <code>MenuBar</code>.
+ */
+ String generateName()
+ {
+ return "menubar" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_menubar_number++;
+ }
/**
* This class provides accessibility support for AWT menu bars.
diff --git a/java/awt/MenuComponent.java b/java/awt/MenuComponent.java
index 9bb875069..163092685 100644
--- a/java/awt/MenuComponent.java
+++ b/java/awt/MenuComponent.java
@@ -200,8 +200,22 @@ public abstract class MenuComponent implements Serializable
*/
public String getName()
{
+ if (name == null && ! nameExplicitlySet)
+ name = generateName();
return name;
}
+
+ /**
+ * Subclasses should override this to return unique component names like
+ * "menuitem0".
+ *
+ * @return the generated name for this menu component
+ */
+ String generateName()
+ {
+ // MenuComponent is abstract.
+ return null;
+ }
/**
* Sets the name of this component to the specified name.
diff --git a/java/awt/MenuItem.java b/java/awt/MenuItem.java
index a7ac79643..7cbc9219f 100644
--- a/java/awt/MenuItem.java
+++ b/java/awt/MenuItem.java
@@ -63,9 +63,15 @@ public class MenuItem extends MenuComponent
/*
* Static Variables
*/
+
+
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_menuitem_number;
-// Serialization Constant
-private static final long serialVersionUID = -21757335363267194L;
+ // Serialization Constant
+ private static final long serialVersionUID = - 21757335363267194L;
/*************************************************************************/
@@ -599,4 +605,19 @@ public AccessibleContext getAccessibleContext()
return accessibleContext;
}
+/**
+ * Generate a unique name for this <code>MenuItem</code>.
+ *
+ * @return A unique name for this <code>MenuItem</code>.
+ */
+String generateName()
+{
+ return "menuitem" + getUniqueLong();
+}
+
+private static synchronized long getUniqueLong()
+{
+ return next_menuitem_number++;
+}
+
} // class MenuItem
diff --git a/java/awt/MouseInfo.java b/java/awt/MouseInfo.java
new file mode 100644
index 000000000..957b6bccb
--- /dev/null
+++ b/java/awt/MouseInfo.java
@@ -0,0 +1,95 @@
+/* MouseInfo.java -- utility methods for mice.
+ 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.awt;
+
+import gnu.java.awt.ClasspathToolkit;
+import java.awt.peer.MouseInfoPeer;
+
+/**
+ * MouseInfo is a class containing utility functions for mouse information.
+ *
+ * @author Sven de Marothy
+ * @since 1.5
+ */
+public class MouseInfo
+{
+ private static MouseInfoPeer peer;
+
+ /**
+ * Returns a PointerInfo object containing information about the current
+ * location of the mouse pointer
+ *
+ * @throws HeadlessException if the current GraphicsEnvironment is headless.
+ * @return a PointerInfo object.
+ */
+ public static PointerInfo getPointerInfo() throws HeadlessException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission( new AWTPermission("watchMousePointer") );
+
+ if( GraphicsEnvironment.isHeadless() )
+ throw new HeadlessException();
+
+ if( peer == null )
+ peer = Toolkit.getDefaultToolkit().getMouseInfoPeer();
+
+ Point p = new Point();
+ int screen = peer.fillPointWithCoords( p );
+
+ GraphicsDevice[] gds = GraphicsEnvironment.getLocalGraphicsEnvironment().
+ getScreenDevices();
+
+ return new PointerInfo( gds[ screen ], p );
+ }
+
+ /**
+ * Returns the number of mouse buttons, or -1 if no mouse is connected.
+ * (mentioned in the 1.5 release notes)
+ *
+ * @throws HeadlessException if the current GraphicsEnvironment is headless.
+ * @return an integer number of buttons.
+ */
+ public static int getNumberOfButtons() throws HeadlessException
+ {
+ if( GraphicsEnvironment.isHeadless() )
+ throw new HeadlessException();
+ return ((ClasspathToolkit)Toolkit.getDefaultToolkit()).
+ getMouseNumberOfButtons();
+ }
+}
diff --git a/java/awt/PointerInfo.java b/java/awt/PointerInfo.java
new file mode 100644
index 000000000..14d44a69b
--- /dev/null
+++ b/java/awt/PointerInfo.java
@@ -0,0 +1,84 @@
+/* PointerInfo.java -- mouse pointer data
+ 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.awt;
+
+/**
+ * PointerInfo represents information about the mouse pointer,
+ * i.e. its GraphicsDevice and location.
+ *
+ * PointerInfo objects cannot be instantiated directly, but are
+ * retrieved from MouseInfo.getPointerInfo(). PointerInfo objects
+ * are immutable and will not be updated for future mouse motions.
+ *
+ * @since 1.5
+ * @author Sven de Marothy
+ */
+public class PointerInfo
+{
+ private GraphicsDevice gd;
+ private Point p;
+
+ /**
+ * Package-private constructor used by MouseInfo.
+ */
+ PointerInfo( GraphicsDevice gd, Point p )
+ {
+ this.gd = gd;
+ this.p = p;
+ }
+
+ /**
+ * Returns the GraphicsDevice on which the mouse pointer was located
+ *
+ * @return a GraphicsDevice object.
+ */
+ public GraphicsDevice getDevice()
+ {
+ return gd;
+ }
+
+ /**
+ * Returns the coordinates of the mouse pointer.
+ *
+ * @return a Point object containing the pointer coordinates.
+ */
+ public Point getLocation()
+ {
+ return p;
+ }
+}
diff --git a/java/awt/PopupMenu.java b/java/awt/PopupMenu.java
index 540fffda7..926867802 100644
--- a/java/awt/PopupMenu.java
+++ b/java/awt/PopupMenu.java
@@ -55,8 +55,13 @@ public class PopupMenu extends Menu
* Static Variables
*/
-// Serialization Constant
-private static final long serialVersionUID = -4620452533522760060L;
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_popup_number;
+
+ // Serialization Constant
+ private static final long serialVersionUID = - 4620452533522760060L;
/*************************************************************************/
@@ -166,6 +171,21 @@ show(Component component, int x, int y)
accessibleContext = new AccessibleAWTPopupMenu();
return accessibleContext;
}
+
+ /**
+ * Generate a unique name for this <code>PopupMenu</code>.
+ *
+ * @return A unique name for this <code>PopupMenu</code>.
+ */
+ String generateName()
+ {
+ return "popup" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_popup_number++;
+ }
} // class PopupMenu
diff --git a/java/awt/ScrollPane.java b/java/awt/ScrollPane.java
index 525d9d3e7..65ce484b8 100644
--- a/java/awt/ScrollPane.java
+++ b/java/awt/ScrollPane.java
@@ -46,6 +46,7 @@ import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
+
/**
* This widget provides a scrollable region that allows a single
* subcomponent to be viewed through a smaller window.
@@ -76,6 +77,11 @@ public static final int SCROLLBARS_ALWAYS = 1;
*/
public static final int SCROLLBARS_NEVER = 2;
+/**
+ * The number used to generate the name returned by getName.
+ */
+private static transient long next_scrollpane_number;
+
// Serialization constant
private static final long serialVersionUID = 7956609840827222915L;
@@ -221,7 +227,7 @@ getVAdjustable()
* @return The viewport size.
*/
public Dimension getViewportSize ()
-{
+{
Dimension viewsize = getSize ();
Insets insets = getInsets ();
@@ -231,9 +237,9 @@ public Dimension getViewportSize ()
Component[] list = getComponents();
if ((list == null) || (list.length <= 0))
return viewsize;
-
+
Dimension dim = list[0].getPreferredSize();
-
+
if (dim.width <= 0 && dim.height <= 0)
return viewsize;
@@ -276,7 +282,7 @@ public Dimension getViewportSize ()
needHorizontal = true;
else if (dim.width > (viewsize.width - vScrollbarWidth))
mayNeedHorizontal = true;
-
+
if (needVertical && mayNeedHorizontal)
needHorizontal = true;
@@ -288,7 +294,7 @@ public Dimension getViewportSize ()
if (needVertical)
viewsize.width -= vScrollbarWidth;
-
+
return viewsize;
}
@@ -613,5 +619,21 @@ paramString()
accessibleContext = new AccessibleAWTScrollPane();
return accessibleContext;
}
+
+ /**
+ * Generate a unique name for this <code>ScrollPane</code>.
+ *
+ * @return A unique name for this <code>ScrollPane</code>.
+ */
+ String generateName()
+ {
+ return "scrollpane" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_scrollpane_number++;
+ }
+
} // class ScrollPane
diff --git a/java/awt/TextField.java b/java/awt/TextField.java
index 1ee07c2d3..b76f393a0 100644
--- a/java/awt/TextField.java
+++ b/java/awt/TextField.java
@@ -54,7 +54,13 @@ import javax.accessibility.AccessibleStateSet;
*/
public class TextField extends TextComponent
{
+
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_textfield_number;
+
private static final long serialVersionUID = -2966288784432217853L;
@@ -434,6 +440,21 @@ public class TextField extends TextComponent
{
return (ActionListener[]) getListeners (ActionListener.class);
}
+
+ /**
+ * Generate a unique name for this <code>TextField</code>.
+ *
+ * @return A unique name for this <code>TextField</code>.
+ */
+ String generateName()
+ {
+ return "textfield" + getUniqueLong();
+ }
+
+ private static synchronized long getUniqueLong()
+ {
+ return next_textfield_number++;
+ }
protected class AccessibleAWTTextField extends AccessibleAWTTextComponent
{
diff --git a/java/awt/Toolkit.java b/java/awt/Toolkit.java
index 4000cb53e..08c0cc67f 100644
--- a/java/awt/Toolkit.java
+++ b/java/awt/Toolkit.java
@@ -70,6 +70,7 @@ import java.awt.peer.ListPeer;
import java.awt.peer.MenuBarPeer;
import java.awt.peer.MenuItemPeer;
import java.awt.peer.MenuPeer;
+import java.awt.peer.MouseInfoPeer;
import java.awt.peer.PanelPeer;
import java.awt.peer.PopupMenuPeer;
import java.awt.peer.ScrollPanePeer;
@@ -130,6 +131,11 @@ public abstract class Toolkit
AWTEventListenerProxy[] awtEventListeners;
/**
+ * The shared peer for all lightweight components.
+ */
+ private GLightweightPeer lightweightPeer;
+
+ /**
* Default constructor for subclasses.
*/
public Toolkit()
@@ -332,6 +338,18 @@ public abstract class Toolkit
protected abstract MenuItemPeer createMenuItem(MenuItem target);
/**
+ * Returns a MouseInfoPeer.
+ * The default implementation of this method throws
+ * UnsupportedOperationException.
+ *
+ * Toolkit implementations should overload this if possible, however.
+ */
+ protected MouseInfoPeer getMouseInfoPeer()
+ {
+ throw new UnsupportedOperationException("No mouse info peer.");
+ }
+
+ /**
* Creates a peer object for the specified <code>FileDialog</code>.
*
* @param target The <code>FileDialog</code> to create the peer for.
@@ -366,7 +384,9 @@ public abstract class Toolkit
*/
protected LightweightPeer createComponent(Component target)
{
- return new GLightweightPeer(target);
+ if (lightweightPeer == null)
+ lightweightPeer = new GLightweightPeer();
+ return lightweightPeer;
}
/**
diff --git a/java/awt/Window.java b/java/awt/Window.java
index 8bc4715ae..888582181 100644
--- a/java/awt/Window.java
+++ b/java/awt/Window.java
@@ -39,8 +39,6 @@ exception statement from your version. */
package java.awt;
import java.awt.event.ComponentEvent;
-import java.awt.event.FocusEvent;
-import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.awt.event.WindowListener;
@@ -80,6 +78,8 @@ public class Window extends Container implements Accessible
private int state = 0;
/** @since 1.4 */
private boolean focusableWindowState = true;
+ /** @since 1.5 */
+ private boolean alwaysOnTop = false;
// A list of other top-level windows owned by this window.
private transient Vector ownedWindows = new Vector();
@@ -130,7 +130,6 @@ public class Window extends Container implements Accessible
// cycle roots.
focusCycleRoot = true;
setLayout(new BorderLayout());
- addWindowFocusListener();
GraphicsEnvironment g = GraphicsEnvironment.getLocalGraphicsEnvironment();
graphicsConfiguration = g.getDefaultScreenDevice().getDefaultConfiguration();
@@ -142,67 +141,6 @@ public class Window extends Container implements Accessible
graphicsConfiguration = gc;
}
- private void addWindowFocusListener()
- {
- addWindowFocusListener(new WindowAdapter()
- {
- public void windowGainedFocus(WindowEvent event)
- {
- EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
- if (windowFocusOwner != null)
- {
- synchronized (eq)
- {
- KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
- Component currentFocusOwner = manager.getGlobalPermanentFocusOwner();
- if (currentFocusOwner != null)
- {
- eq.postEvent(new FocusEvent(currentFocusOwner,
- FocusEvent.FOCUS_LOST, false,
- windowFocusOwner));
- eq.postEvent(new FocusEvent(windowFocusOwner,
- FocusEvent.FOCUS_GAINED, false,
- currentFocusOwner));
- }
- else
- eq.postEvent(new FocusEvent(windowFocusOwner,
- FocusEvent.FOCUS_GAINED, false));
- }
- }
- else
- eq.postEvent(new FocusEvent(Window.this, FocusEvent.FOCUS_GAINED,
- false));
- }
-
- public void windowLostFocus(WindowEvent event)
- {
- EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
- if (windowFocusOwner != null)
- {
- synchronized (eq)
- {
- KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
- Component currentFocusOwner = manager.getGlobalPermanentFocusOwner();
- if (currentFocusOwner != null)
- {
- eq.postEvent(new FocusEvent(currentFocusOwner,
- FocusEvent.FOCUS_GAINED, false,
- windowFocusOwner));
- eq.postEvent(new FocusEvent(windowFocusOwner,
- FocusEvent.FOCUS_LOST, false,
- currentFocusOwner));
- }
- else
- eq.postEvent(new FocusEvent(windowFocusOwner,
- FocusEvent.FOCUS_LOST, false));
- }
- }
- else
- eq.postEvent(new FocusEvent(Window.this, FocusEvent.FOCUS_LOST, false));
- }
- });
- }
-
/**
* Initializes a new instance of <code>Window</code> with the specified
* parent. The window will initially be invisible.
@@ -420,13 +358,17 @@ public class Window extends Container implements Accessible
/**
* Sends this window to the back so that all other windows display in
* front of it.
+ *
+ * If the window is set to be always-on-top, this will remove its
+ * always-on-top status.
*/
public void toBack()
{
if (peer != null)
{
- WindowPeer wp = (WindowPeer) peer;
- wp.toBack();
+ if( alwaysOnTop )
+ setAlwaysOnTop( false );
+ ( (WindowPeer) peer ).toBack();
}
}
@@ -437,10 +379,7 @@ public class Window extends Container implements Accessible
public void toFront()
{
if (peer != null)
- {
- WindowPeer wp = (WindowPeer) peer;
- wp.toFront();
- }
+ ( (WindowPeer) peer ).toFront();
}
/**
@@ -1236,6 +1175,55 @@ public class Window extends Container implements Accessible
}
/**
+ * Returns whether the Windows is an always-on-top window,
+ * meaning whether the window can be obscured by other windows or not.
+ *
+ * @return <code>true</code> if the windows is always-on-top,
+ * <code>false</code> otherwise.
+ * @since 1.5
+ */
+ public final boolean isAlwaysOnTop()
+ {
+ return alwaysOnTop;
+ }
+
+ /**
+ * Sets the always-on-top state of this window (if supported).
+ *
+ * Setting a window to always-on-top means it will not be obscured
+ * by any other windows (with the exception of other always-on-top
+ * windows). Not all platforms may support this.
+ *
+ * If an window's always-on-top status is changed to false, the window
+ * will remain at the front but not be anchored there.
+ *
+ * Calling toBack() on an always-on-top window will change its
+ * always-on-top status to false.
+ *
+ * @since 1.5
+ */
+ public final void setAlwaysOnTop(boolean alwaysOnTop)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission( new AWTPermission("setWindowAlwaysOnTop") );
+
+ if( this.alwaysOnTop == alwaysOnTop )
+ return;
+
+ if( alwaysOnTop )
+ toFront();
+
+ firePropertyChange("alwaysOnTop", this.alwaysOnTop, alwaysOnTop );
+ this.alwaysOnTop = alwaysOnTop;
+
+ if (peer != null)
+ ( (WindowPeer) peer).updateAlwaysOnTop();
+ else
+ System.out.println("Null peer?!");
+ }
+
+ /**
* Generate a unique name for this window.
*
* @return A unique name for this window.
diff --git a/java/awt/dnd/DragGestureRecognizer.java b/java/awt/dnd/DragGestureRecognizer.java
index 32bbc56da..2327a5ee1 100644
--- a/java/awt/dnd/DragGestureRecognizer.java
+++ b/java/awt/dnd/DragGestureRecognizer.java
@@ -164,6 +164,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/java/awt/dnd/DragSource.java b/java/awt/dnd/DragSource.java
index 57b4fac12..f57749559 100644
--- a/java/awt/dnd/DragSource.java
+++ b/java/awt/dnd/DragSource.java
@@ -51,7 +51,6 @@ import java.awt.datatransfer.FlavorMap;
import java.awt.datatransfer.SystemFlavorMap;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.peer.DragSourceContextPeer;
-import java.awt.event.MouseMotionListener;
import java.io.Serializable;
import java.util.EventListener;
@@ -77,6 +76,8 @@ public class DragSource implements Serializable
private transient DragSourceMotionListener dragSourceMotionListener;
private static DragSource ds;
+ private DragSourceContextPeer peer;
+ private DragSourceContext context;
/**
* Initializes the drag source.
@@ -104,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;
}
@@ -139,13 +139,16 @@ 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.
-
+
try
{
flavorMap = map;
- DragSourceContextPeer peer = Toolkit.getDefaultToolkit().
- createDragSourceContextPeer(trigger);
- DragSourceContext context = createDragSourceContext(peer, trigger,
+
+ if (peer == null)
+ peer = Toolkit.getDefaultToolkit().createDragSourceContextPeer(trigger);
+
+ if (context == null)
+ context = createDragSourceContext(peer, trigger,
dragCursor,
dragImage,
imageOffset, trans,
@@ -306,4 +309,17 @@ public class DragSource implements Serializable
// Return an empty EventListener array.
return new EventListener [0];
}
+
+ /**
+ * TODO
+ * @return TODO
+ *
+ * @since 1.5
+ */
+ public static int getDragThreshold()
+ throws NotImplementedException
+ {
+ // FIXME: Not implemented.
+ return 8;
+ }
} // class DragSource
diff --git a/java/awt/dnd/DropTarget.java b/java/awt/dnd/DropTarget.java
index 2698b1dae..1e7b2c4cd 100644
--- a/java/awt/dnd/DropTarget.java
+++ b/java/awt/dnd/DropTarget.java
@@ -45,10 +45,12 @@ import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Point;
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;
import java.awt.peer.ComponentPeer;
+import java.awt.peer.LightweightPeer;
import java.io.Serializable;
import java.util.EventListener;
import java.util.TooManyListenersException;
@@ -112,7 +114,7 @@ public class DropTarget
*/
public DropTarget ()
{
- this (null, 0, null, true, null);
+ this (null, DnDConstants.ACTION_COPY_OR_MOVE, null, true, null);
}
/**
@@ -123,7 +125,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);
}
/**
@@ -160,12 +162,19 @@ public class DropTarget
if (GraphicsEnvironment.isHeadless ())
throw new HeadlessException ();
- component = c;
- actions = i;
+ setComponent(c);
+ setDefaultActions(i);
dropTargetListener = dtl;
- flavorMap = fm;
+
+ if (fm == null)
+ flavorMap = SystemFlavorMap.getDefaultFlavorMap();
+ else
+ flavorMap = fm;
setActive (b);
+
+ if (c != null)
+ c.setDropTarget(this);
}
/**
@@ -221,8 +230,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;
}
@@ -275,9 +290,16 @@ public class DropTarget
public void addNotify(ComponentPeer p)
{
+ Component c = component;
+ while (c != null && p instanceof LightweightPeer)
+ {
+ p = c.getPeer();
+ c = c.getParent();
+ }
+
if (p instanceof DropTargetPeer)
{
- peer = (DropTargetPeer) p;
+ peer = ((DropTargetPeer) p);
peer.addDropTarget(this);
}
else
diff --git a/java/awt/dnd/DropTargetDragEvent.java b/java/awt/dnd/DropTargetDragEvent.java
index 1aaae8a29..89bf1778a 100644
--- a/java/awt/dnd/DropTargetDragEvent.java
+++ b/java/awt/dnd/DropTargetDragEvent.java
@@ -40,6 +40,7 @@ package java.awt.dnd;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
import java.util.List;
/**
@@ -136,4 +137,17 @@ public class DropTargetDragEvent extends DropTargetEvent
{
context.rejectDrag ();
}
+
+ /**
+ * TODO
+ *
+ * @return
+ *
+ * @since 1.5
+ */
+ public Transferable getTransferable()
+ {
+ // FIXME: Not implemented
+ return null;
+ }
} // class DropTargetDragEvent
diff --git a/java/awt/font/FontRenderContext.java b/java/awt/font/FontRenderContext.java
index c50e5e509..c25bae3ec 100644
--- a/java/awt/font/FontRenderContext.java
+++ b/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/java/awt/font/TextLayout.java b/java/awt/font/TextLayout.java
index 17f1d029e..b1473f255 100644
--- a/java/awt/font/TextLayout.java
+++ b/java/awt/font/TextLayout.java
@@ -664,8 +664,9 @@ public final class TextLayout implements Cloneable
}
public TextHitInfo hitTestChar (float x, float y, Rectangle2D bounds)
+ throws NotImplementedException
{
- return hitTestChar( x, y, getBounds() );
+ throw new Error ("not implemented");
}
public boolean isLeftToRight ()
diff --git a/java/awt/font/TextMeasurer.java b/java/awt/font/TextMeasurer.java
index e91c7ef16..00cab8a87 100644
--- a/java/awt/font/TextMeasurer.java
+++ b/java/awt/font/TextMeasurer.java
@@ -128,6 +128,8 @@ public final class TextMeasurer implements Cloneable
*/
public TextLayout getLayout (int start, int limit)
{
+ if( start >= limit )
+ throw new IllegalArgumentException("Start position must be < limit.");
return new TextLayout( totalLayout, start, limit );
}
diff --git a/java/awt/geom/AffineTransform.java b/java/awt/geom/AffineTransform.java
index 55b688355..5bc51ddee 100644
--- a/java/awt/geom/AffineTransform.java
+++ b/java/awt/geom/AffineTransform.java
@@ -1401,10 +1401,10 @@ public class AffineTransform implements Cloneable, Serializable
* documented, but appears to be the same as:
* <pre>
* long l = Double.doubleToLongBits(getScaleX());
- * l = l * 31 + Double.doubleToLongBits(getShearY());
* l = l * 31 + Double.doubleToLongBits(getShearX());
- * l = l * 31 + Double.doubleToLongBits(getScaleY());
* l = l * 31 + Double.doubleToLongBits(getTranslateX());
+ * l = l * 31 + Double.doubleToLongBits(getShearY());
+ * l = l * 31 + Double.doubleToLongBits(getScaleY());
* l = l * 31 + Double.doubleToLongBits(getTranslateY());
* return (int) ((l >> 32) ^ l);
* </pre>
@@ -1413,12 +1413,12 @@ public class AffineTransform implements Cloneable, Serializable
*/
public int hashCode()
{
- long l = Double.doubleToLongBits(m00);
- l = l * 31 + Double.doubleToLongBits(m10);
- l = l * 31 + Double.doubleToLongBits(m01);
- l = l * 31 + Double.doubleToLongBits(m11);
- l = l * 31 + Double.doubleToLongBits(m02);
- l = l * 31 + Double.doubleToLongBits(m12);
+ long l = Double.doubleToLongBits(m00);
+ l = l * 31 + Double.doubleToLongBits(m01);
+ l = l * 31 + Double.doubleToLongBits(m02);
+ l = l * 31 + Double.doubleToLongBits(m10);
+ l = l * 31 + Double.doubleToLongBits(m11);
+ l = l * 31 + Double.doubleToLongBits(m12);
return (int) ((l >> 32) ^ l);
}
diff --git a/java/awt/geom/GeneralPath.java b/java/awt/geom/GeneralPath.java
index 0dcc116ed..e0ca8e183 100644
--- a/java/awt/geom/GeneralPath.java
+++ b/java/awt/geom/GeneralPath.java
@@ -65,8 +65,8 @@ import java.awt.Shape;
* &#x2019;up&#x2019;
* direction, one in the &#x2019;down&#x2019; direction) Point <b>B</b> in
* the image is inside (one intersection &#x2019;down&#x2019;)
- * Point <b>C</b> in the image is outside (two intersections
- * &#x2019;down&#x2019;)
+ * Point <b>C</b> in the image is inside (two intersections in the
+ * &#x2019;down&#x2019; direction)
*
* @see Line2D
* @see CubicCurve2D
diff --git a/java/awt/image/BandedSampleModel.java b/java/awt/image/BandedSampleModel.java
index 24d315a1c..afe62bdc4 100644
--- a/java/awt/image/BandedSampleModel.java
+++ b/java/awt/image/BandedSampleModel.java
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004, 2005, Free Software Foundation
+/* Copyright (C) 2004, 2005, 2006, Free Software Foundation
This file is part of GNU Classpath.
@@ -36,10 +36,11 @@ exception statement from your version. */
package java.awt.image;
+import gnu.java.awt.Buffers;
+
/**
- * MultiPixelPackedSampleModel provides a single band model that supports
- * multiple pixels in a single unit. Pixels have 2^n bits and 2^k pixels fit
- * per data element.
+ * A sample model that reads each sample value from a separate band in the
+ * {@link DataBuffer}.
*
* @author Jerry Quinn (jlquinn@optonline.net)
*/
@@ -61,17 +62,61 @@ public final class BandedSampleModel extends ComponentSampleModel
return result;
}
+ /**
+ * Creates a new <code>BandedSampleModel</code>.
+ *
+ * @param dataType the data buffer type.
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ * @param numBands the number of bands.
+ */
public BandedSampleModel(int dataType, int w, int h, int numBands)
{
this(dataType, w, h, w, createBankArray(numBands), new int[numBands]);
}
+ /**
+ * Creates a new <code>BandedSampleModel</code>.
+ *
+ * @param dataType the data buffer type.
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ * @param scanlineStride the number of data elements from a pixel in one
+ * row to the corresponding pixel in the next row.
+ * @param bankIndices the bank indices.
+ * @param bandOffsets the band offsets.
+ */
public BandedSampleModel(int dataType, int w, int h, int scanlineStride,
int[] bankIndices, int[] bandOffsets)
{
super(dataType, w, h, 1, scanlineStride, bankIndices, bandOffsets);
}
+
+ /**
+ * Creates a new data buffer that is compatible with this sample model.
+ *
+ * @return The new data buffer.
+ */
+ public DataBuffer createDataBuffer()
+ {
+ int size = scanlineStride * height;
+ return Buffers.createBuffer(getDataType(), size, numBanks);
+ }
+ /**
+ * Creates a new <code>SampleModel</code> that is compatible with this
+ * model and has the specified width and height.
+ *
+ * @param w the width (in pixels, must be greater than zero).
+ * @param h the height (in pixels, must be greater than zero).
+ *
+ * @return The new sample model.
+ *
+ * @throws IllegalArgumentException if <code>w</code> or <code>h</code> is
+ * not greater than zero.
+ * @throws IllegalArgumentException if <code>w * h</code> exceeds
+ * <code>Integer.MAX_VALUE</code>.
+ */
public SampleModel createCompatibleSampleModel(int w, int h)
{
// NOTE: blackdown 1.4.1 sets all offsets to 0. Sun's 1.4.2 docs
@@ -80,32 +125,32 @@ public final class BandedSampleModel extends ComponentSampleModel
// Compress offsets so minimum is 0, others w*scanlineStride
int[] newoffsets = new int[bandOffsets.length];
int[] order = new int[bandOffsets.length];
- for (int i=0; i < bandOffsets.length; i++)
+ for (int i = 0; i < bandOffsets.length; i++)
order[i] = i;
// FIXME: This is N^2, but not a big issue, unless there's a lot of
// bands...
- for (int i=0; i < bandOffsets.length; i++)
- for (int j=i+1; j < bandOffsets.length; i++)
- if (bankIndices[order[i]] > bankIndices[order[j]]
- || (bankIndices[order[i]] == bankIndices[order[j]]
- && bandOffsets[order[i]] > bandOffsets[order[j]]))
- {
- int t = order[i]; order[i] = order[j]; order[j] = t;
- }
+ for (int i = 0; i < bandOffsets.length; i++)
+ for (int j = i + 1; j < bandOffsets.length; j++)
+ if (bankIndices[order[i]] > bankIndices[order[j]]
+ || (bankIndices[order[i]] == bankIndices[order[j]]
+ && bandOffsets[order[i]] > bandOffsets[order[j]]))
+ {
+ int t = order[i]; order[i] = order[j]; order[j] = t;
+ }
int bank = 0;
int offset = 0;
- for (int i=0; i < bandOffsets.length; i++)
+ for (int i = 0; i < bandOffsets.length; i++)
{
- if (bankIndices[order[i]] != bank)
- {
- bank = bankIndices[order[i]];
- offset = 0;
- }
- newoffsets[order[i]] = offset;
- offset += w * scanlineStride;
+ if (bankIndices[order[i]] != bank)
+ {
+ bank = bankIndices[order[i]];
+ offset = 0;
+ }
+ newoffsets[order[i]] = offset;
+ offset += w * scanlineStride;
}
- return new BandedSampleModel(dataType, w, h, scanlineStride, bankIndices, newoffsets);
+ return new BandedSampleModel(dataType, w, h, w, bankIndices, newoffsets);
}
@@ -117,7 +162,7 @@ public final class BandedSampleModel extends ComponentSampleModel
+" many bands");
int[] newoff = new int[bands.length];
int[] newbanks = new int[bands.length];
- for (int i=0; i < bands.length; i++)
+ for (int i = 0; i < bands.length; i++)
{
int b = bands[i];
newoff[i] = bandOffsets[b];
@@ -134,57 +179,64 @@ public final class BandedSampleModel extends ComponentSampleModel
* Extracts the pixel at x, y from data and stores samples into the array
* obj. If obj is null, a new array of getTransferType() is created.
*
- * @param x The x-coordinate of the pixel rectangle to store in <code>obj</code>.
- * @param y The y-coordinate of the pixel rectangle to store in <code>obj</code>.
- * @param obj The primitive array to store the pixels into or null to force creation.
+ * @param x The x-coordinate of the pixel rectangle to store in
+ * <code>obj</code>.
+ * @param y The y-coordinate of the pixel rectangle to store in
+ * <code>obj</code>.
+ * @param obj The primitive array to store the pixels into or null to force
+ * creation.
* @param data The DataBuffer that is the source of the pixel data.
* @return The primitive array containing the pixel data.
- * @see java.awt.image.SampleModel#getDataElements(int, int, java.lang.Object, java.awt.image.DataBuffer)
+ * @see java.awt.image.SampleModel#getDataElements(int, int,
+ * java.lang.Object, java.awt.image.DataBuffer)
*/
- public Object getDataElements(int x, int y, Object obj,
- DataBuffer data)
+ public Object getDataElements(int x, int y, Object obj, DataBuffer data)
{
+ if (x < 0 || y < 0)
+ throw new ArrayIndexOutOfBoundsException(
+ "x and y must not be less than 0.");
int pixel = getSample(x, y, 0, data);
switch (getTransferType())
{
case DataBuffer.TYPE_BYTE:
{
- byte[] b = (byte[])obj;
+ byte[] b = (byte[]) obj;
if (b == null) b = new byte[numBands];
- for (int i=0; i < numBands; i++)
+ for (int i = 0; i < numBands; i++)
b[i] = (byte)getSample(x, y, i, data);
return b;
}
case DataBuffer.TYPE_SHORT:
case DataBuffer.TYPE_USHORT:
{
- short[] b = (short[])obj;
+ short[] b = (short[]) obj;
if (b == null) b = new short[numBands];
- for (int i=0; i < numBands; i++)
+ for (int i = 0; i < numBands; i++)
b[i] = (short)getSample(x, y, i, data);
return b;
}
case DataBuffer.TYPE_INT:
{
- int[] b = (int[])obj;
+ int[] b = (int[]) obj;
if (b == null) b = new int[numBands];
- for (int i=0; i < numBands; i++)
+ for (int i = 0; i < numBands; i++)
b[i] = getSample(x, y, i, data);
return b;
}
case DataBuffer.TYPE_FLOAT:
{
- float[] b = (float[])obj;
+ float[] b = (float[]) obj;
if (b == null) b = new float[numBands];
- for (int i=0; i < numBands; i++)
+ for (int i = 0; i < numBands; i++)
b[i] = getSampleFloat(x, y, i, data);
return b;
}
case DataBuffer.TYPE_DOUBLE:
{
- double[] b = (double[])obj;
- if (b == null) b = new double[numBands];
- for (int i=0; i < numBands; i++)
+ double[] b = (double[]) obj;
+ if (b == null)
+ b = new double[numBands];
+ for (int i = 0; i < numBands; i++)
b[i] = getSample(x, y, i, data);
return b;
}
@@ -195,10 +247,27 @@ public final class BandedSampleModel extends ComponentSampleModel
}
}
+ /**
+ * Returns all the samples for the pixel at location <code>(x, y)</code>
+ * stored in the specified data buffer.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param iArray an array that will be populated with the sample values and
+ * returned as the result. The size of this array should be equal to the
+ * number of bands in the model. If the array is <code>null</code>, a new
+ * array is created.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The samples for the specified pixel.
+ *
+ * @see #setPixel(int, int, int[], DataBuffer)
+ */
public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
{
- if (iArray == null) iArray = new int[numBands];
- for (int i=0; i < numBands; i++)
+ if (iArray == null)
+ iArray = new int[numBands];
+ for (int i = 0; i < numBands; i++)
iArray[i] = getSample(x, y, i, data);
return iArray;
@@ -228,7 +297,11 @@ public final class BandedSampleModel extends ComponentSampleModel
public int[] getPixels(int x, int y, int w, int h, int[] iArray,
DataBuffer data)
{
- if (iArray == null) iArray = new int[w*h*numBands];
+ if (x < 0 || y < 0)
+ throw new ArrayIndexOutOfBoundsException(
+ "x and y must not be less than 0.");
+ if (iArray == null)
+ iArray = new int[w * h * numBands];
int outOffset = 0;
int maxX = x + w;
int maxY = y + h;
@@ -247,18 +320,64 @@ public final class BandedSampleModel extends ComponentSampleModel
return iArray;
}
+ /**
+ * Returns a sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public int getSample(int x, int y, int b, DataBuffer data)
{
int offset = bandOffsets[b] + y * scanlineStride + x;
return data.getElem(bankIndices[b], offset);
}
+ /**
+ * Returns a sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ *
+ * @see #getSample(int, int, int, DataBuffer)
+ */
public float getSampleFloat(int x, int y, int b, DataBuffer data)
{
int offset = bandOffsets[b] + y * scanlineStride + x;
return data.getElemFloat(bankIndices[b], offset);
}
+ /**
+ * Returns the sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ *
+ * @see #getSample(int, int, int, DataBuffer)
+ */
public double getSampleDouble(int x, int y, int b, DataBuffer data)
{
int offset = bandOffsets[b] + y * scanlineStride + x;
@@ -288,7 +407,11 @@ public final class BandedSampleModel extends ComponentSampleModel
public int[] getSamples(int x, int y, int w, int h, int b, int[] iArray,
DataBuffer data)
{
- if (iArray == null) iArray = new int[w*h];
+ if (x < 0 || y < 0)
+ throw new ArrayIndexOutOfBoundsException(
+ "x and y must not be less than 0.");
+ if (iArray == null)
+ iArray = new int[w * h];
int outOffset = 0;
int maxX = x + w;
int maxY = y + h;
@@ -304,7 +427,6 @@ public final class BandedSampleModel extends ComponentSampleModel
return iArray;
}
-
/**
* Set the pixel at x, y to the value in the first element of the primitive
* array obj.
@@ -338,7 +460,7 @@ public final class BandedSampleModel extends ComponentSampleModel
{
DataBufferByte out = (DataBufferByte) data;
byte[] in = (byte[]) obj;
- for (int i=0; i < numBands; i++)
+ for (int i = 0; i < numBands; i++)
out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
return;
}
@@ -346,7 +468,7 @@ public final class BandedSampleModel extends ComponentSampleModel
{
DataBufferShort out = (DataBufferShort) data;
short[] in = (short[]) obj;
- for (int i=0; i < numBands; i++)
+ for (int i = 0; i < numBands; i++)
out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
return;
}
@@ -354,7 +476,7 @@ public final class BandedSampleModel extends ComponentSampleModel
{
DataBufferUShort out = (DataBufferUShort) data;
short[] in = (short[]) obj;
- for (int i=0; i < numBands; i++)
+ for (int i = 0; i < numBands; i++)
out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
return;
}
@@ -362,7 +484,7 @@ public final class BandedSampleModel extends ComponentSampleModel
{
DataBufferInt out = (DataBufferInt) data;
int[] in = (int[]) obj;
- for (int i=0; i < numBands; i++)
+ for (int i = 0; i < numBands; i++)
out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
return;
}
@@ -370,7 +492,7 @@ public final class BandedSampleModel extends ComponentSampleModel
{
DataBufferFloat out = (DataBufferFloat) data;
float[] in = (float[]) obj;
- for (int i=0; i < numBands; i++)
+ for (int i = 0; i < numBands; i++)
out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
return;
}
@@ -378,7 +500,7 @@ public final class BandedSampleModel extends ComponentSampleModel
{
DataBufferDouble out = (DataBufferDouble) data;
double[] in = (double[]) obj;
- for (int i=0; i < numBands; i++)
+ for (int i = 0; i < numBands; i++)
out.getData(bankIndices[i])[offset + bandOffsets[i]] = in[i];
return;
}
@@ -388,26 +510,54 @@ public final class BandedSampleModel extends ComponentSampleModel
}
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;
+ 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);
}
}
+ /**
+ * Sets the samples for the pixel at (x, y) in the specified data buffer to
+ * the specified values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
public void setPixel(int x, int y, int[] iArray, DataBuffer data)
{
- for (int b=0; b < numBands; b++)
+ for (int b = 0; b < numBands; b++)
data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x,
iArray[b]);
}
+ /**
+ * Sets the sample values for the pixels in the region specified by
+ * (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param iArray the pixel sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
public void setPixels(int x, int y, int w, int h, int[] iArray,
DataBuffer data)
{
@@ -417,7 +567,7 @@ public final class BandedSampleModel extends ComponentSampleModel
for (int ww = 0; ww < w; ww++)
{
int offset = y * scanlineStride + (x + ww);
- for (int b=0; b < numBands; b++)
+ for (int b = 0; b < numBands; b++)
data.setElem(bankIndices[b], bandOffsets[b] + offset,
iArray[inOffset++]);
}
@@ -425,24 +575,83 @@ public final class BandedSampleModel extends ComponentSampleModel
}
}
+ /**
+ * Sets the sample value for band <code>b</code> of the pixel at location
+ * <code>(x, y)</code> in the specified data buffer.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param b the band index.
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @see #getSample(int, int, int, DataBuffer)
+ */
public void setSample(int x, int y, int b, int s, DataBuffer data)
{
data.setElem(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s);
}
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the
+ * specified data buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public void setSample(int x, int y, int b, float s, DataBuffer data)
{
- data.setElemFloat(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s);
+ data.setElemFloat(bankIndices[b], bandOffsets[b] + y * scanlineStride + x,
+ s);
}
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the
+ * specified data buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public void setSample(int x, int y, int b, double s, DataBuffer data)
{
- data.setElemDouble(bankIndices[b], bandOffsets[b] + y * scanlineStride + x, s);
+ data.setElemDouble(bankIndices[b], bandOffsets[b] + y * scanlineStride + x,
+ s);
}
+ /**
+ * Sets the sample values for one band for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer.
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param iArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
public void setSamples(int x, int y, int w, int h, int b, int[] iArray,
DataBuffer data)
{
+ if (x < 0 || y < 0)
+ throw new ArrayIndexOutOfBoundsException(
+ "x and y must not be less than 0.");
int inOffset = 0;
switch (getTransferType())
@@ -537,9 +746,10 @@ public final class BandedSampleModel extends ComponentSampleModel
result.append(getClass().getName());
result.append("[");
result.append("scanlineStride=").append(scanlineStride);
- for(int i=0; i < bitMasks.length; i+=1)
+ for(int i = 0; i < bitMasks.length; i+=1)
{
- result.append(", mask[").append(i).append("]=0x").append(Integer.toHexString(bitMasks[i]));
+ result.append(", mask[").append(i).append("]=0x").append(
+ Integer.toHexString(bitMasks[i]));
}
result.append("]");
diff --git a/java/awt/image/BufferedImage.java b/java/awt/image/BufferedImage.java
index 0b0730009..fe40451e8 100644
--- a/java/awt/image/BufferedImage.java
+++ b/java/awt/image/BufferedImage.java
@@ -79,151 +79,209 @@ 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;
/**
- * Creates a new buffered image.
+ * The image's WritableRaster
+ */
+ WritableRaster raster;
+
+ /**
+ * The associated ColorModel
+ */
+ ColorModel colorModel;
+
+ /**
+ * The image's properties (or null)
+ */
+ Hashtable properties;
+
+ /**
+ * Whether alpha is premultiplied
+ */
+ boolean isPremultiplied;
+
+ /**
+ * The predefined type, if any.
+ */
+ int type;
+
+ /**
+ * Creates a new <code>BufferedImage</code> with the specified width, height
+ * and type. Valid <code>type</code> values are:
+ *
+ * <ul>
+ * <li>{@link #TYPE_INT_RGB}</li>
+ * <li>{@link #TYPE_INT_ARGB}</li>
+ * <li>{@link #TYPE_INT_ARGB_PRE}</li>
+ * <li>{@link #TYPE_INT_BGR}</li>
+ * <li>{@link #TYPE_3BYTE_BGR}</li>
+ * <li>{@link #TYPE_4BYTE_ABGR}</li>
+ * <li>{@link #TYPE_4BYTE_ABGR_PRE}</li>
+ * <li>{@link #TYPE_USHORT_565_RGB}</li>
+ * <li>{@link #TYPE_USHORT_555_RGB}</li>
+ * <li>{@link #TYPE_BYTE_GRAY}</li>
+ * <li>{@link #TYPE_USHORT_GRAY}</li>
+ * <li>{@link #TYPE_BYTE_BINARY}</li>
+ * <li>{@link #TYPE_BYTE_INDEXED}</li>
+ * </ul>
+ *
+ * @param w the width (must be > 0).
+ * @param h the height (must be > 0).
+ * @param type the image type (see the list of valid types above).
*
- * @param w the width.
- * @param h the height.
- * @param type the image type (see the constants defined by this class).
+ * @throws IllegalArgumentException if <code>w</code> or <code>h</code> is
+ * less than or equal to zero.
+ * @throws IllegalArgumentException if <code>type</code> is not one of the
+ * specified values.
*/
- public BufferedImage(int w, int h, int type)
+ public BufferedImage(int width, int height, int type)
{
+ SampleModel sm = null;
ColorModel cm = null;
-
- boolean alpha = false;
- boolean premultiplied = false;
- switch (type)
- {
- case TYPE_4BYTE_ABGR_PRE:
- case TYPE_INT_ARGB_PRE:
- premultiplied = true;
- // fall through
- case TYPE_INT_ARGB:
- case TYPE_4BYTE_ABGR:
- alpha = true;
- }
-
- ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
- switch (type)
+ boolean premultiplied = (type == BufferedImage.TYPE_INT_ARGB_PRE ||
+ type == BufferedImage.TYPE_4BYTE_ABGR_PRE);
+
+ switch( type )
{
- case TYPE_INT_RGB:
- case TYPE_INT_ARGB:
- case TYPE_INT_ARGB_PRE:
- case TYPE_USHORT_565_RGB:
- case TYPE_USHORT_555_RGB:
- int[] masks = null;
- switch (type)
- {
- case TYPE_INT_RGB:
- case TYPE_INT_ARGB:
- case TYPE_INT_ARGB_PRE:
- masks = masks_int;
- break;
- case TYPE_USHORT_565_RGB:
- masks = masks_565;
- break;
- case TYPE_USHORT_555_RGB:
- masks = masks_555;
- break;
- }
-
- cm = new DirectColorModel(cs,
- 32, // 32 bits in an int
- masks[0], // r
- masks[1], // g
- masks[2], // b
- alpha ? 0xff000000 : 0,
- premultiplied,
- masks[3] // data type
- );
+ case BufferedImage.TYPE_INT_RGB:
+ sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT,
+ width, height,
+ new int[]{ 0x00FF0000,
+ 0x0000FF00,
+ 0x000000FF } ) ;
+ cm = new DirectColorModel( 24, 0xff0000, 0xff00, 0xff );
break;
- case TYPE_INT_BGR:
- String msg =
- "FIXME: Programmer is confused. Why (and how) does a " +
- "TYPE_INT_BGR image use ComponentColorModel to store " +
- "8-bit values? Is data type TYPE_INT or TYPE_BYTE. What " +
- "is the difference between TYPE_INT_BGR and TYPE_3BYTE_BGR?";
- throw new UnsupportedOperationException(msg);
-
- case TYPE_3BYTE_BGR:
- case TYPE_4BYTE_ABGR:
- case TYPE_4BYTE_ABGR_PRE:
- case TYPE_BYTE_GRAY:
- case TYPE_USHORT_GRAY:
- int[] bits = null;
- int dataType = DataBuffer.TYPE_BYTE;
- switch (type) {
- case TYPE_3BYTE_BGR:
- bits = bits3;
- break;
- case TYPE_4BYTE_ABGR:
- case TYPE_4BYTE_ABGR_PRE:
- bits = bits4;
- break;
- case TYPE_BYTE_GRAY:
- bits = bits1byte;
- break;
- case TYPE_USHORT_GRAY:
- bits = bits1ushort;
- 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 DirectColorModel( 24, 0xff, 0xff00, 0xff0000 );
+ 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 } );
+ cm = new DirectColorModel( 32, 0xff0000, 0xff00, 0xff, 0xff000000 );
break;
- case TYPE_BYTE_BINARY:
- byte[] vals = { 0, (byte) 0xff };
- cm = new IndexColorModel(8, 2, vals, vals, vals);
+
+ case BufferedImage.TYPE_4BYTE_ABGR:
+ case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+ sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT,
+ width, height,
+ new int[]{ 0x000000FF,
+ 0xFF000000,
+ 0x00FF0000,
+ 0x0000FF00 } );
+ cm = new DirectColorModel( 32, 0xff, 0xff00, 0xff0000, 0xff000000 );
break;
- case TYPE_BYTE_INDEXED:
- String msg2 = "type not implemented yet";
- throw new UnsupportedOperationException(msg2);
- // FIXME: build color-cube and create color model
+
+ case BufferedImage.TYPE_INT_BGR:
+ sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT,
+ width, height,
+ new int[]{ 0x000000FF,
+ 0x0000FF00,
+ 0x00FF0000 } ) ;
+ cm = new DirectColorModel( 32, 0xff, 0xff00, 0xff0000 );
+ break;
+
+ case BufferedImage.TYPE_USHORT_565_RGB:
+ sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_USHORT,
+ width, height,
+ new int[]{ 0x0000001F,
+ 0x000007E0,
+ 0x0000F800 } ) ;
+ cm = new DirectColorModel( 16, 0x1F, 0x7E0, 0xf800 );
+ break;
+ case BufferedImage.TYPE_USHORT_555_RGB:
+ sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_USHORT,
+ width, height,
+ new int[]{ 0x0000001F,
+ 0x000003E0,
+ 0x00007C00 } ) ;
+ cm = new DirectColorModel( 15, 0x1F, 0x3E0, 0x7c00 );
+ break;
+
+ 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;
+
+ default:
+ 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,
@@ -233,15 +291,9 @@ public class BufferedImage extends Image
{
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,
@@ -254,8 +306,43 @@ public class BufferedImage extends Image
isPremultiplied = premultiplied;
this.type = type;
}
-
- //public void addTileObserver(TileObserver tileobserver) {}
+
+ /**
+ * Creates the default palettes for the predefined indexed color types
+ * (256-color or black-and-white)
+ *
+ * @param binary - If <code>true</code>, a black and white palette,
+ * otherwise a default 256-color palette is returned.
+ */
+ private IndexColorModel createDefaultIndexedColorModel( boolean binary )
+ {
+ if( binary )
+ {
+ byte[] t = new byte[]{ 0, (byte)255 };
+ return new IndexColorModel( 1, 2, t, t, t );
+ }
+
+ byte[] r = new byte[256];
+ byte[] g = new byte[256];
+ byte[] b = new byte[256];
+ int index = 0;
+ for( int i = 0; i < 6; i++ )
+ for( int j = 0; j < 6; j++ )
+ for( int k = 0; k < 6; k++ )
+ {
+ r[ index ] = (byte)(i * 51);
+ g[ index ] = (byte)(j * 51);
+ b[ index ] = (byte)(k * 51);
+ index++;
+ }
+ while( index < 256 )
+ {
+ r[ index ] = g[ index ] = b[ index ] =
+ (byte)(18 + (index - 216) * 6);
+ index++;
+ }
+ return new IndexColorModel( 8, 256, r, g, b );
+ }
public void coerceData(boolean premultiplied)
{
@@ -700,10 +787,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);
}
/**
@@ -715,10 +802,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/java/awt/image/BufferedImageOp.java b/java/awt/image/BufferedImageOp.java
index 2ecbec056..f6a24c976 100644
--- a/java/awt/image/BufferedImageOp.java
+++ b/java/awt/image/BufferedImageOp.java
@@ -1,5 +1,5 @@
/* BufferedImageOp.java --
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -43,13 +43,65 @@ import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
/**
- * NEEDS DOCUMENTATION
+ * An operation that is performed on one <code>BufferedImage</code> (the
+ * source) producing a new <code>BufferedImage</code> (the destination).
*/
public interface BufferedImageOp
{
+ /**
+ * Performs an operation on the source image, returning the result in a
+ * <code>BufferedImage</code>. If <code>dest</code> is <code>null</code>, a
+ * new <code>BufferedImage</code> will be created by calling the
+ * {@link #createCompatibleDestImage} method. If <code>dest</code>
+ * is not <code>null</code>, the result is written to <code>dest</code> then
+ * returned (this avoids creating a new <code>BufferedImage</code> each
+ * time this method is called).
+ *
+ * @param src the source image.
+ * @param dst the destination image (<code>null</code> permitted).
+ *
+ * @return The filterd image.
+ */
BufferedImage filter(BufferedImage src, BufferedImage dst);
+
+ /**
+ * Returns the bounds of the destination image on the basis of this
+ * <code>BufferedImageOp</code> being applied to the specified source image.
+ *
+ * @param src the source image.
+ *
+ * @return The destination bounds.
+ */
Rectangle2D getBounds2D(BufferedImage src);
+
+ /**
+ * Returns a new <code>BufferedImage</code> that can be used by this
+ * <code>BufferedImageOp</code> as the destination image when filtering
+ * the specified source image.
+ *
+ * @param src the source image.
+ * @param dstCM the color model for the destination image.
+ *
+ * @return A new image that can be used as the destination image.
+ */
BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM);
+
+ /**
+ * Returns the point on the destination image that corresponds to the given
+ * point on the source image.
+ *
+ * @param src the source point.
+ * @param dst the destination point (<code>null</code> permitted).
+ *
+ * @return The destination point.
+ */
Point2D getPoint2D(Point2D src, Point2D dst);
+
+ /**
+ * Returns the rendering hints for this operation.
+ *
+ * @return The rendering hints.
+ */
RenderingHints getRenderingHints();
-} // interface BufferedImageOp
+
+}
diff --git a/java/awt/image/ByteLookupTable.java b/java/awt/image/ByteLookupTable.java
index df02d0a1b..ecc0023af 100644
--- a/java/awt/image/ByteLookupTable.java
+++ b/java/awt/image/ByteLookupTable.java
@@ -1,5 +1,5 @@
/* ByteLookupTable.java -- Java class for a pixel translation table.
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -60,14 +60,20 @@ public class ByteLookupTable extends LookupTable
* components.
*
* @param offset Offset to be subtracted.
- * @param data Array of lookup tables.
+ * @param data Array of lookup tables (<code>null</code> not permitted).
* @exception IllegalArgumentException if offset &lt; 0 or data.length &lt; 1.
*/
public ByteLookupTable(int offset, byte[][] data)
throws IllegalArgumentException
{
super(offset, data.length);
- this.data = data;
+
+ // tests show that Sun's implementation creates a new array to store the
+ // references from the incoming 'data' array - not sure why, but we'll
+ // match that behaviour just in case it matters...
+ this.data = new byte[data.length][];
+ for (int i = 0; i < data.length; i++)
+ this.data[i] = data[i];
}
/**
@@ -77,13 +83,16 @@ public class ByteLookupTable extends LookupTable
* table. The same table is applied to all pixel components.
*
* @param offset Offset to be subtracted.
- * @param data Lookup table for all components.
+ * @param data Lookup table for all components (<code>null</code> not
+ * permitted).
* @exception IllegalArgumentException if offset &lt; 0.
*/
public ByteLookupTable(int offset, byte[] data)
throws IllegalArgumentException
{
super(offset, 1);
+ if (data == null)
+ throw new NullPointerException("Null 'data' argument.");
this.data = new byte[][] {data};
}
diff --git a/java/awt/image/ColorConvertOp.java b/java/awt/image/ColorConvertOp.java
index 18609e0c4..1f85a5ecd 100644
--- a/java/awt/image/ColorConvertOp.java
+++ b/java/awt/image/ColorConvertOp.java
@@ -1,5 +1,5 @@
-/* ColorModel.java --
- Copyright (C) 2004 Free Software Foundation
+/* ColorConvertOp.java --
+ Copyright (C) 2004, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -177,8 +177,7 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp
ColorModel scm = src.getColorModel();
for (int i = 0; i < spaces.length; i++)
{
- ColorModel cm = scm.cloneColorModel(spaces[i]);
- BufferedImage tmp = createCompatibleDestImage(src, cm);
+ BufferedImage tmp = createCompatibleDestImage(src, scm);
copyimage(src, tmp);
src = tmp;
}
@@ -189,6 +188,7 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp
// Apply final conversion
copyimage(src, dst);
+
return dst;
}
@@ -287,7 +287,12 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp
private void copyimage(BufferedImage src, BufferedImage dst)
{
Graphics2D gg = dst.createGraphics();
- gg.setRenderingHints(hints);
+
+ // If no hints are set there is no need to call
+ // setRenderingHints on the Graphics2D object.
+ if (hints != null)
+ gg.setRenderingHints(hints);
+
gg.drawImage(src, 0, 0, null);
gg.dispose();
}
diff --git a/java/awt/image/ColorModel.java b/java/awt/image/ColorModel.java
index e2f5378b4..9e559db37 100644
--- a/java/awt/image/ColorModel.java
+++ b/java/awt/image/ColorModel.java
@@ -1,5 +1,5 @@
/* ColorModel.java --
- Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation
+ Copyright (C) 1999, 2000, 2002, 2003, 2004, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -43,7 +43,6 @@ import gnu.java.awt.Buffers;
import java.awt.Point;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
-import java.lang.reflect.Constructor;
import java.util.Arrays;
/**
@@ -163,32 +162,6 @@ public abstract class ColorModel implements Transparency
this.transparency = transparency;
this.transferType = transferType;
}
-
- // This is a hook for ColorConvertOp to create a colormodel with
- // a new colorspace
- ColorModel cloneColorModel(ColorSpace cspace)
- {
- Class cls = this.getClass();
- ColorModel cm;
- try {
- // This constructor will exist.
- Constructor ctor =
- cls.getConstructor(new Class[]{int.class, int[].class,
- ColorSpace.class, boolean.class,
- boolean.class, int.class, int.class});
- cm = (ColorModel)ctor.
- newInstance(new Object[]{new Integer(pixel_bits),
- bits, cspace, Boolean.valueOf(hasAlpha),
- Boolean.valueOf(isAlphaPremultiplied),
- new Integer(transparency),
- new Integer(transferType)});
- }
- catch (Exception e)
- {
- throw new IllegalArgumentException();
- }
- return cm;
- }
public void finalize()
{
diff --git a/java/awt/image/ComponentSampleModel.java b/java/awt/image/ComponentSampleModel.java
index b4e9450b0..bccabbbca 100644
--- a/java/awt/image/ComponentSampleModel.java
+++ b/java/awt/image/ComponentSampleModel.java
@@ -272,9 +272,7 @@ public class ComponentSampleModel extends SampleModel
// Maybe this value should be precalculated in the constructor?
int highestOffset = 0;
for (int b = 0; b < numBands; b++)
- {
- highestOffset = Math.max(highestOffset, bandOffsets[b]);
- }
+ highestOffset = Math.max(highestOffset, bandOffsets[b]);
int size = pixelStride * (width - 1) + scanlineStride * (height - 1)
+ highestOffset + 1;
@@ -678,6 +676,9 @@ public class ComponentSampleModel extends SampleModel
*/
public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
{
+ if (x < 0 || x >= width || y < 0 || y >= height)
+ throw new ArrayIndexOutOfBoundsException("Pixel (" + x + ", " + y
+ + ") is out of bounds.");
int offset = pixelStride * x + scanlineStride * y;
if (iArray == null)
iArray = new int[numBands];
@@ -736,10 +737,16 @@ public class ComponentSampleModel extends SampleModel
*
* @return The sample value.
*
+ * @throws ArrayIndexOutOfBoundsException if <code>(x, y)</code> is outside
+ * the bounds <code>[0, 0, width, height]</code>.
+ *
* @see #setSample(int, int, int, int, DataBuffer)
*/
public int getSample(int x, int y, int b, DataBuffer data)
{
+ if (x < 0 || x >= width || y < 0 || y >= height)
+ throw new ArrayIndexOutOfBoundsException("Sample (" + x + ", " + y
+ + ") is out of bounds.");
return data.getElem(bankIndices[b], getOffset(x, y, b));
}
diff --git a/java/awt/image/ConvolveOp.java b/java/awt/image/ConvolveOp.java
index 1f73f75b2..ffb834874 100644
--- a/java/awt/image/ConvolveOp.java
+++ b/java/awt/image/ConvolveOp.java
@@ -1,5 +1,5 @@
/* ConvolveOp.java --
- Copyright (C) 2004, 2005 Free Software Foundation -- ConvolveOp
+ Copyright (C) 2004, 2005, 2006, Free Software Foundation -- ConvolveOp
This file is part of GNU Classpath.
@@ -42,7 +42,6 @@ import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
-import java.util.Arrays;
/**
* Convolution filter.
@@ -190,112 +189,101 @@ public class ConvolveOp implements BufferedImageOp, RasterOp
* @see java.awt.image.RasterOp#filter(java.awt.image.Raster,
* java.awt.image.WritableRaster)
*/
- public final WritableRaster filter(Raster src, WritableRaster dest) {
+ public final WritableRaster filter(Raster src, WritableRaster dest)
+ {
if (src == dest)
- throw new IllegalArgumentException();
- if (src.getWidth() < kernel.getWidth() ||
- src.getHeight() < kernel.getHeight())
- throw new ImagingOpException(null);
-
+ throw new IllegalArgumentException("src == dest is not allowed.");
+ if (kernel.getWidth() > src.getWidth()
+ || kernel.getHeight() > src.getHeight())
+ throw new ImagingOpException("The kernel is too large.");
if (dest == null)
dest = createCompatibleDestRaster(src);
- else if (src.numBands != dest.numBands)
- throw new ImagingOpException(null);
+ else if (src.getNumBands() != dest.getNumBands())
+ throw new ImagingOpException("src and dest have different band counts.");
- // Deal with bottom edge
- if (edge == EDGE_ZERO_FILL)
- {
- float[] zeros = new float[src.getNumBands() * src.getWidth()
- * (kernel.getYOrigin() - 1)];
- Arrays.fill(zeros, 0);
- dest.setPixels(src.getMinX(), src.getMinY(), src.getWidth(),
- kernel.getYOrigin() - 1, zeros);
- }
- else
- {
- float[] vals = new float[src.getNumBands() * src.getWidth()
- * (kernel.getYOrigin() - 1)];
- src.getPixels(src.getMinX(), src.getMinY(), src.getWidth(),
- kernel.getYOrigin() - 1, vals);
- dest.setPixels(src.getMinX(), src.getMinY(), src.getWidth(),
- kernel.getYOrigin() - 1, vals);
- }
+ // calculate the borders that the op can't reach...
+ int kWidth = kernel.getWidth();
+ int kHeight = kernel.getHeight();
+ int left = kernel.getXOrigin();
+ int right = Math.max(kWidth - left - 1, 0);
+ int top = kernel.getYOrigin();
+ int bottom = Math.max(kHeight - top - 1, 0);
- // Handle main section
+ // process the region that is reachable...
+ int regionW = src.width - left - right;
+ int regionH = src.height - top - bottom;
float[] kvals = kernel.getKernelData(null);
+ float[] tmp = new float[kWidth * kHeight];
- float[] tmp = new float[kernel.getWidth() * kernel.getHeight()];
- for (int y = src.getMinY() + kernel.getYOrigin();
- y < src.getMinY() + src.getHeight() - kernel.getYOrigin() / 2; y++)
- {
- // Handle unfiltered edge pixels at start of line
- float[] t1 = new float[(kernel.getXOrigin() - 1) * src.getNumBands()];
- if (edge == EDGE_ZERO_FILL)
- Arrays.fill(t1, 0);
- else
- src.getPixels(src.getMinX(), y, kernel.getXOrigin() - 1, 1, t1);
- dest.setPixels(src.getMinX(), y, kernel.getXOrigin() - 1, 1, t1);
-
- for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ for (int x = 0; x < regionW; x++)
{
- // FIXME: This needs a much more efficient implementation
- for (int b = 0; b < src.getNumBands(); b++)
- {
- float v = 0;
- src.getSamples(x, y, kernel.getWidth(), kernel.getHeight(), b, tmp);
- for (int i=0; i < tmp.length; i++)
- v += tmp[i] * kvals[i];
- dest.setSample(x, y, b, v);
- }
+ for (int y = 0; y < regionH; y++)
+ {
+ // FIXME: This needs a much more efficient implementation
+ for (int b = 0; b < src.getNumBands(); b++)
+ {
+ float v = 0;
+ src.getSamples(x, y, kWidth, kHeight, b, tmp);
+ for (int i = 0; i < tmp.length; i++)
+ v += tmp[tmp.length - i - 1] * kvals[i];
+ // FIXME: in the above line, I've had to reverse the order of
+ // the samples array to make the tests pass. I haven't worked
+ // out why this is necessary.
+ dest.setSample(x + kernel.getXOrigin(), y + kernel.getYOrigin(),
+ b, v);
+ }
+ }
}
-
- // Handle unfiltered edge pixels at end of line
- float[] t2 = new float[(kernel.getWidth() / 2) * src.getNumBands()];
- if (edge == EDGE_ZERO_FILL)
- Arrays.fill(t2, 0);
- else
- src.getPixels(src.getMinX() + src.getWidth()
- - (kernel.getWidth() / 2),
- y, kernel.getWidth() / 2, 1, t2);
- dest.setPixels(src.getMinX() + src.getWidth() - (kernel.getWidth() / 2),
- y, kernel.getWidth() / 2, 1, t2);
- }
- for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
- for (int x = src.getMinX(); x< src.getWidth() + src.getMinX(); x++)
+
+ // fill in the top border
+ fillEdge(src, dest, 0, 0, src.width, top, edge);
+
+ // fill in the bottom border
+ fillEdge(src, dest, 0, src.height - bottom, src.width, bottom, edge);
+
+ // fill in the left border
+ fillEdge(src, dest, 0, top, left, regionH, edge);
+
+ // fill in the right border
+ fillEdge(src, dest, src.width - right, top, right, regionH, edge);
+
+ return dest;
+ }
+
+ /**
+ * Fills a range of pixels (typically at the edge of a raster) with either
+ * zero values (if <code>edgeOp</code> is <code>EDGE_ZERO_FILL</code>) or the
+ * corresponding pixel values from the source raster (if <code>edgeOp</code>
+ * is <code>EDGE_NO_OP</code>). This utility method is called by the
+ * {@link #fillEdge(Raster, WritableRaster, int, int, int, int, int)} method.
+ *
+ * @param src the source raster.
+ * @param dest the destination raster.
+ * @param x the x-coordinate of the top left pixel in the range.
+ * @param y the y-coordinate of the top left pixel in the range.
+ * @param w the width of the pixel range.
+ * @param h the height of the pixel range.
+ * @param edgeOp indicates how to determine the values for the range
+ * (either {@link #EDGE_ZERO_FILL} or {@link #EDGE_NO_OP}).
+ */
+ private void fillEdge(Raster src, WritableRaster dest, int x, int y, int w,
+ int h, int edgeOp)
+ {
+ if (w <= 0)
+ return;
+ if (h <= 0)
+ return;
+ if (edgeOp == EDGE_ZERO_FILL) // fill region with zeroes
{
-
+ float[] zeros = new float[src.getNumBands() * w * h];
+ dest.setPixels(x, y, w, h, zeros);
}
- for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
- for (int x = src.getMinX(); x< src.getWidth() + src.getMinX(); x++)
+ else // copy pixels from source
{
-
+ float[] pixels = new float[src.getNumBands() * w * h];
+ src.getPixels(x, y, w, h, pixels);
+ dest.setPixels(x, y, w, h, pixels);
}
-
- // Handle top edge
- if (edge == EDGE_ZERO_FILL)
- {
- float[] zeros = new float[src.getNumBands() * src.getWidth() *
- (kernel.getHeight() / 2)];
- Arrays.fill(zeros, 0);
- dest.setPixels(src.getMinX(),
- src.getHeight() + src.getMinY() - (kernel.getHeight() / 2),
- src.getWidth(), kernel.getHeight() / 2, zeros);
- }
- else
- {
- float[] vals = new float[src.getNumBands() * src.getWidth() *
- (kernel.getHeight() / 2)];
- src.getPixels(src.getMinX(),
- src.getHeight() + src.getMinY()
- - (kernel.getHeight() / 2),
- src.getWidth(), kernel.getHeight() / 2, vals);
- dest.setPixels(src.getMinX(),
- src.getHeight() + src.getMinY()
- - (kernel.getHeight() / 2),
- src.getWidth(), kernel.getHeight() / 2, vals);
- }
-
- return dest;
}
/* (non-Javadoc)
diff --git a/java/awt/image/DataBuffer.java b/java/awt/image/DataBuffer.java
index 9e4f71418..5a2cfd3b0 100644
--- a/java/awt/image/DataBuffer.java
+++ b/java/awt/image/DataBuffer.java
@@ -114,8 +114,7 @@ public abstract class DataBuffer
*/
protected DataBuffer(int dataType, int size)
{
- this.dataType = dataType;
- this.size = size;
+ this(dataType, size, 1);
}
/**
@@ -132,9 +131,7 @@ public abstract class DataBuffer
* @param numBanks the number of data banks.
*/
protected DataBuffer(int dataType, int size, int numBanks) {
- this(dataType, size);
- banks = numBanks;
- offsets = new int[numBanks];
+ this(dataType, size, numBanks, 0);
}
/**
@@ -153,11 +150,14 @@ public abstract class DataBuffer
* @param offset the offset to the first element for all banks.
*/
protected DataBuffer(int dataType, int size, int numBanks, int offset) {
- this(dataType, size, numBanks);
-
- java.util.Arrays.fill(offsets, offset);
-
+ banks = numBanks;
+ this.dataType = dataType;
+ this.size = size;
this.offset = offset;
+
+ offsets = new int[ numBanks ];
+ for(int i = 0; i < numBanks; i++ )
+ offsets[i] = offset;
}
/**
@@ -179,10 +179,11 @@ public abstract class DataBuffer
* <code>numBanks != offsets.length</code>.
*/
protected DataBuffer(int dataType, int size, int numBanks, int[] offsets) {
- this(dataType, size);
if (numBanks != offsets.length)
throw new ArrayIndexOutOfBoundsException();
-
+
+ this.dataType = dataType;
+ this.size = size;
banks = numBanks;
this.offsets = offsets;
diff --git a/java/awt/image/Kernel.java b/java/awt/image/Kernel.java
index f7c29c3cd..8361c0cf9 100644
--- a/java/awt/image/Kernel.java
+++ b/java/awt/image/Kernel.java
@@ -1,5 +1,5 @@
/* Kernel.java -- Java class for an image processing kernel
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -44,21 +44,32 @@ package java.awt.image;
* values representing a 2-dimensional array in row-major order.
*
* @author Jerry Quinn (jlquinn@optonline.net)
- * @version 1.0
*/
public class Kernel implements Cloneable
{
+ /** The kernel width. */
private final int width;
+
+ /** The kernel height. */
private final int height;
+
+ /** Internal storage for the kernel's values. */
private final float[] data;
/**
- * Creates a new <code>Kernel</code> instance.
+ * Creates a new <code>Kernel</code> instance with the specified dimensions
+ * and values. The first <code>width * height</code> values in the specified
+ * <code>data</code> array are copied to internal storage.
*
- * @param width The 2D width of data.
- * @param height The 2D height of data.
- * @param data The source data array.
- * @exception IllegalArgumentException if width * height < data.length.
+ * @param width the kernel width.
+ * @param height the kernel height.
+ * @param data the source data array (<code>null</code> not permitted).
+ *
+ * @throws IllegalArgumentException if <code>data.length</code> is less than
+ * <code>width * height</code>.
+ * @throws IllegalArgumentException if <code>width</code> or
+ * <code>height</code> is less than zero.
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
*/
public Kernel(int width, int height, float[] data)
throws IllegalArgumentException
@@ -72,7 +83,10 @@ public class Kernel implements Cloneable
}
/**
- * Return the X origin: (width - 1) / 2
+ * Returns the x-origin for the kernel, which is calculated as
+ * <code>(width - 1) / 2</code>.
+ *
+ * @return The x-origin for the kernel.
*/
public final int getXOrigin()
{
@@ -80,7 +94,10 @@ public class Kernel implements Cloneable
}
/**
- * Return the Y origin: (height - 1) / 2
+ * Returns the y-origin for the kernel, which is calculated as
+ * <code>(height - 1) / 2</code>.
+ *
+ * @return The y-origin for the kernel.
*/
public final int getYOrigin()
{
@@ -88,6 +105,8 @@ public class Kernel implements Cloneable
}
/**
+ * Returns the kernel width (as supplied to the constructor).
+ *
* @return The kernel width.
*/
public final int getWidth()
@@ -96,6 +115,8 @@ public class Kernel implements Cloneable
}
/**
+ * Returns the kernel height (as supplied to the constructor).
+ *
* @return The kernel height.
*/
public final int getHeight()
@@ -104,20 +125,25 @@ public class Kernel implements Cloneable
}
/**
- * Return the kernel data.
+ * Returns an array containing a copy of the kernel data. If the
+ * <code>data</code> argument is non-<code>null</code>, the kernel values
+ * are copied into it and then <code>data</code> is returned as the result.
+ * If the <code>data</code> argument is <code>null</code>, this method
+ * allocates a new array then populates and returns it.
*
- * If data is null, allocates a new array and returns it. Otherwise, the
- * kernel values are copied into data.
- *
- * @param data Array to copy values into, or null.
+ * @param data an array to copy the return values into (if
+ * <code>null</code>, a new array is allocated).
+ *
* @return The array with copied values.
- * @exception IllegalArgumentException if data != null and too small.
+ *
+ * @throws IllegalArgumentException if <code>data.length</code> is less than
+ * the kernel's <code>width * height</code>.
*/
public final float[] getKernelData(float[] data)
throws IllegalArgumentException
{
if (data == null)
- return (float[])this.data.clone();
+ return (float[]) this.data.clone();
if (data.length < this.data.length)
throw new IllegalArgumentException();
@@ -127,13 +153,15 @@ public class Kernel implements Cloneable
}
/**
+ * Returns a clone of this kernel.
+ *
* @return a clone of this Kernel.
*/
public Object clone()
{
try
{
- return super.clone();
+ return super.clone();
}
catch (CloneNotSupportedException e)
{
diff --git a/java/awt/image/MultiPixelPackedSampleModel.java b/java/awt/image/MultiPixelPackedSampleModel.java
index 18a6e5552..8732e5765 100644
--- a/java/awt/image/MultiPixelPackedSampleModel.java
+++ b/java/awt/image/MultiPixelPackedSampleModel.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.
@@ -56,12 +56,43 @@ public class MultiPixelPackedSampleModel extends SampleModel
private int numberOfBits;
private int numElems;
+ /**
+ * Creates a new <code>MultiPixelPackedSampleModel</code> with the specified
+ * data type, which should be one of:
+ * <ul>
+ * <li>{@link DataBuffer#TYPE_BYTE};</li>
+ * <li>{@link DataBuffer#TYPE_USHORT};</li>
+ * <li>{@link DataBuffer#TYPE_INT};</li>
+ * </ul>
+ *
+ * @param dataType the data type.
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ * @param numberOfBits the number of bits per pixel (must be a power of 2).
+ */
public MultiPixelPackedSampleModel(int dataType, int w, int h,
int numberOfBits)
{
this(dataType, w, h, numberOfBits, 0, 0);
}
+ /**
+ * Creates a new <code>MultiPixelPackedSampleModel</code> with the specified
+ * data type, which should be one of:
+ * <ul>
+ * <li>{@link DataBuffer#TYPE_BYTE};</li>
+ * <li>{@link DataBuffer#TYPE_USHORT};</li>
+ * <li>{@link DataBuffer#TYPE_INT};</li>
+ * </ul>
+ *
+ * @param dataType the data type.
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ * @param numberOfBits the number of bits per pixel (must be a power of 2).
+ * @param scanlineStride the number of data elements from a pixel on one
+ * row to the corresponding pixel in the next row.
+ * @param dataBitOffset the offset to the first data bit.
+ */
public MultiPixelPackedSampleModel(int dataType, int w, int h,
int numberOfBits, int scanlineStride,
int dataBitOffset)
@@ -101,7 +132,7 @@ public class MultiPixelPackedSampleModel extends SampleModel
// Compute scan line large enough for w pixels.
if (scanlineStride == 0)
- scanlineStride = ((dataBitOffset + w * numberOfBits) / elemBits);
+ scanlineStride = ((dataBitOffset + w * numberOfBits) - 1) / elemBits + 1;
this.scanlineStride = scanlineStride;
@@ -118,6 +149,16 @@ public class MultiPixelPackedSampleModel extends SampleModel
}
}
+ /**
+ * Creates a new <code>MultiPixelPackedSample</code> model with the same
+ * data type and bits per pixel as this model, but with the specified
+ * dimensions.
+ *
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ *
+ * @return The new sample model.
+ */
public SampleModel createCompatibleSampleModel(int w, int h)
{
/* FIXME: We can avoid recalculation of bit offsets and sample
@@ -126,78 +167,163 @@ public class MultiPixelPackedSampleModel extends SampleModel
return new MultiPixelPackedSampleModel(dataType, w, h, numberOfBits);
}
-
/**
* Creates a DataBuffer for holding pixel data in the format and
* layout described by this SampleModel. The returned buffer will
* consist of one single bank.
+ *
+ * @return A new data buffer.
*/
public DataBuffer createDataBuffer()
{
- int size;
-
- // FIXME: The comment refers to SinglePixelPackedSampleModel. See if the
- // same can be done for MultiPixelPackedSampleModel.
- // We can save (scanlineStride - width) pixels at the very end of
- // the buffer. The Sun reference implementation (J2SE 1.3.1 and
- // 1.4.1_01) seems to do this; tested with Mauve test code.
- size = scanlineStride * height;
-
+ int size = scanlineStride * height;
+ if (dataBitOffset > 0)
+ size += (dataBitOffset - 1) / elemBits + 1;
return Buffers.createBuffer(getDataType(), size);
}
-
+ /**
+ * Returns the number of data elements required to transfer a pixel in the
+ * get/setDataElements() methods.
+ *
+ * @return <code>1</code>.
+ */
public int getNumDataElements()
{
return 1;
}
+ /**
+ * Returns an array containing the size (in bits) of the samples in each
+ * band. The <code>MultiPixelPackedSampleModel</code> class supports only
+ * one band, so this method returns an array with length <code>1</code>.
+ *
+ * @return An array containing the size (in bits) of the samples in band zero.
+ *
+ * @see #getSampleSize(int)
+ */
public int[] getSampleSize()
{
- return sampleSize;
+ return (int[]) sampleSize.clone();
}
+ /**
+ * Returns the size of the samples in the specified band. Note that the
+ * <code>MultiPixelPackedSampleModel</code> supports only one band -- this
+ * method ignored the <code>band</code> argument, and always returns the size
+ * of band zero.
+ *
+ * @param band the band (this parameter is ignored).
+ *
+ * @return The size of the samples in band zero.
+ *
+ * @see #getSampleSize()
+ */
public int getSampleSize(int band)
{
return sampleSize[0];
}
+ /**
+ * Returns the index in the data buffer that stores the pixel at (x, y).
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ *
+ * @return The index in the data buffer that stores the pixel at (x, y).
+ *
+ * @see #getBitOffset(int)
+ */
public int getOffset(int x, int y)
{
- return scanlineStride * y + ((dataBitOffset + x*numberOfBits) / elemBits);
+ return scanlineStride * y + ((dataBitOffset + x * numberOfBits) / elemBits);
}
+ /**
+ * The bit offset (within an element in the data buffer) of the pixels with
+ * the specified x-coordinate.
+ *
+ * @param x the x-coordinate.
+ *
+ * @return The bit offset.
+ */
public int getBitOffset(int x)
{
- return (dataBitOffset + x*numberOfBits) % elemBits;
+ return (dataBitOffset + x * numberOfBits) % elemBits;
}
+ /**
+ * Returns the offset to the first data bit.
+ *
+ * @return The offset to the first data bit.
+ */
public int getDataBitOffset()
{
return dataBitOffset;
}
+ /**
+ * Returns the number of data elements from a pixel in one row to the
+ * corresponding pixel in the next row.
+ *
+ * @return The scanline stride.
+ */
public int getScanlineStride()
{
return scanlineStride;
}
+ /**
+ * Returns the number of bits per pixel.
+ *
+ * @return The number of bits per pixel.
+ */
public int getPixelBitStride()
{
return numberOfBits;
}
+
+ /**
+ * Returns the transfer type, which is one of the following (depending on
+ * the number of bits per sample for this model):
+ * <ul>
+ * <li>{@link DataBuffer#TYPE_BYTE};</li>
+ * <li>{@link DataBuffer#TYPE_USHORT};</li>
+ * <li>{@link DataBuffer#TYPE_INT};</li>
+ * </ul>
+ *
+ * @return The transfer type.
+ */
+ public int getTransferType()
+ {
+ if (numberOfBits <= DataBuffer.getDataTypeSize(DataBuffer.TYPE_BYTE))
+ return DataBuffer.TYPE_BYTE;
+ else if (numberOfBits <= DataBuffer.getDataTypeSize(DataBuffer.TYPE_USHORT))
+ return DataBuffer.TYPE_USHORT;
+ return DataBuffer.TYPE_INT;
+ }
-
+ /**
+ * Normally this method returns a sample model for accessing a subset of
+ * bands of image data, but since <code>MultiPixelPackedSampleModel</code>
+ * only supports a single band, this overridden implementation just returns
+ * a new instance of <code>MultiPixelPackedSampleModel</code>, with the same
+ * attributes as this instance.
+ *
+ * @param bands the bands to include in the subset (this is ignored, except
+ * that if it is non-<code>null</code> a check is made to ensure that the
+ * array length is equal to <code>1</code>).
+ *
+ * @throws RasterFormatException if <code>bands</code> is not
+ * <code>null</code> and <code>bands.length != 1</code>.
+ */
public SampleModel createSubsetSampleModel(int[] bands)
{
- int numBands = bands.length;
- if (numBands != 1)
+ if (bands != null && bands.length != 1)
throw new RasterFormatException("MultiPixelPackedSampleModel only"
- + " supports one band");
-
- return new MultiPixelPackedSampleModel(dataType, width, height,
- numberOfBits, scanlineStride,
- dataBitOffset);
+ + " supports one band");
+ return new MultiPixelPackedSampleModel(dataType, width, height,
+ numberOfBits, scanlineStride, dataBitOffset);
}
/**
@@ -207,68 +333,82 @@ public class MultiPixelPackedSampleModel extends SampleModel
* array obj, since there is only one band. If obj is null, a new array of
* getTransferType() is created.
*
- * @param x The x-coordinate of the pixel rectangle to store in <code>obj</code>.
- * @param y The y-coordinate of the pixel rectangle to store in <code>obj</code>.
- * @param obj The primitive array to store the pixels into or null to force creation.
+ * @param x The x-coordinate of the pixel rectangle to store in
+ * <code>obj</code>.
+ * @param y The y-coordinate of the pixel rectangle to store in
+ * <code>obj</code>.
+ * @param obj The primitive array to store the pixels into or null to force
+ * creation.
* @param data The DataBuffer that is the source of the pixel data.
* @return The primitive array containing the pixel data.
- * @see java.awt.image.SampleModel#getDataElements(int, int, java.lang.Object, java.awt.image.DataBuffer)
+ * @see java.awt.image.SampleModel#getDataElements(int, int, Object,
+ * DataBuffer)
*/
- public Object getDataElements(int x, int y, Object obj,
- DataBuffer data)
+ public Object getDataElements(int x, int y, Object obj, DataBuffer data)
{
int pixel = getSample(x, y, 0, data);
switch (getTransferType())
- {
- case DataBuffer.TYPE_BYTE:
- if (obj == null) obj = new byte[1];
- ((byte[])obj)[0] = (byte)pixel;
- return obj;
- case DataBuffer.TYPE_USHORT:
- if (obj == null) obj = new short[1];
- ((short[])obj)[0] = (short)pixel;
- return obj;
- case DataBuffer.TYPE_INT:
- if (obj == null) obj = new int[1];
- ((int[])obj)[0] = pixel;
- return obj;
- default:
- // Seems like the only sensible thing to do.
- throw new ClassCastException();
- }
+ {
+ case DataBuffer.TYPE_BYTE:
+ if (obj == null)
+ obj = new byte[1];
+ ((byte[]) obj)[0] = (byte) pixel;
+ return obj;
+ case DataBuffer.TYPE_USHORT:
+ if (obj == null)
+ obj = new short[1];
+ ((short[]) obj)[0] = (short) pixel;
+ return obj;
+ case DataBuffer.TYPE_INT:
+ if (obj == null)
+ obj = new int[1];
+ ((int[]) obj)[0] = pixel;
+ return obj;
+ default:
+ // Seems like the only sensible thing to do.
+ throw new ClassCastException();
+ }
}
+ /**
+ * Returns an array (of length 1) containing the sample for the pixel at
+ * (x, y) in the specified data buffer. If <code>iArray</code> is not
+ * <code>null</code>, it will be populated with the sample value and
+ * returned as the result of this function (this avoids allocating a new
+ * array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return An array containing the pixel sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
{
- if (iArray == null) iArray = new int[1];
+ if (iArray == null)
+ iArray = new int[1];
iArray[0] = getSample(x, y, 0, data);
-
return iArray;
}
- public int[] getPixels(int x, int y, int w, int h, int[] iArray,
- DataBuffer data)
- {
- int offset = getOffset(x, y);
- if (iArray == null) iArray = new int[w*h];
- int outOffset = 0;
- for (y=0; y<h; y++)
- {
- int lineOffset = offset;
- for (x=0; x<w;)
- {
- int samples = data.getElem(lineOffset++);
- for (int b=0; b<numElems && x<w; b++)
- {
- iArray[outOffset++] = (samples & bitMasks[b]) >>> bitOffsets[b];
- x++;
- }
- }
- offset += scanlineStride;
- }
- return iArray;
- }
-
+ /**
+ * Returns the sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public int getSample(int x, int y, int b, DataBuffer data)
{
int pos =
@@ -286,72 +426,82 @@ public class MultiPixelPackedSampleModel extends SampleModel
* @param y The y-coordinate of the data elements in <code>obj</code>.
* @param obj The primitive array containing the data elements to set.
* @param data The DataBuffer to store the data elements into.
- * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer)
*/
public void setDataElements(int x, int y, Object obj, DataBuffer data)
{
int transferType = getTransferType();
- if (getTransferType() != data.getDataType())
- {
- throw new IllegalArgumentException("transfer type ("+
- getTransferType()+"), "+
- "does not match data "+
- "buffer type (" +
- data.getDataType() +
- ").");
- }
-
- int offset = getOffset(x, y);
-
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;
- }
- default:
- throw new ClassCastException("Unsupported data type");
- }
+ switch (transferType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ byte[] in = (byte[]) obj;
+ setSample(x, y, 0, in[0] & 0xFF, data);
+ return;
+ }
+ case DataBuffer.TYPE_USHORT:
+ {
+ short[] in = (short[]) obj;
+ setSample(x, y, 0, in[0] & 0xFFFF, data);
+ return;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ int[] in = (int[]) obj;
+ setSample(x, y, 0, in[0], data);
+ return;
+ }
+ default:
+ throw new ClassCastException("Unsupported data type");
+ }
}
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);
+ String msg = "While writing data elements" +
+ ", x=" + x + ", y=" + y +
+ ", width=" + width + ", height=" + height +
+ ", scanlineStride=" + scanlineStride +
+ ", offset=" + getOffset(x, y) +
+ ", data.getSize()=" + data.getSize() +
+ ", data.getOffset()=" + data.getOffset() +
+ ": " + aioobe;
+ throw new ArrayIndexOutOfBoundsException(msg);
}
- }
+ }
+ /**
+ * Sets the sample value for the pixel at (x, y) in the specified data
+ * buffer to the specified value.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray the sample value (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ *
+ * @see #setSample(int, int, int, int, DataBuffer)
+ */
public void setPixel(int x, int y, int[] iArray, DataBuffer data)
{
setSample(x, y, 0, iArray[0], data);
}
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the
+ * specified data buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public void setSample(int x, int y, int b, int s, DataBuffer data)
{
int bitpos =
@@ -367,6 +517,70 @@ public class MultiPixelPackedSampleModel extends SampleModel
}
/**
+ * Tests this sample model for equality with an arbitrary object. This
+ * method returns <code>true</code> if and only if:
+ * <ul>
+ * <li><code>obj</code> is not <code>null</code>;
+ * <li><code>obj</code> is an instance of
+ * <code>MultiPixelPackedSampleModel</code>;
+ * <li>both models have the same:
+ * <ul>
+ * <li><code>dataType</code>;
+ * <li><code>width</code>;
+ * <li><code>height</code>;
+ * <li><code>numberOfBits</code>;
+ * <li><code>scanlineStride</code>;
+ * <li><code>dataBitOffsets</code>.
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * @param obj the object (<code>null</code> permitted)
+ *
+ * @return <code>true</code> if this model is equal to <code>obj</code>, and
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (! (obj instanceof MultiPixelPackedSampleModel))
+ return false;
+ MultiPixelPackedSampleModel that = (MultiPixelPackedSampleModel) obj;
+ if (this.dataType != that.dataType)
+ return false;
+ if (this.width != that.width)
+ return false;
+ if (this.height != that.height)
+ return false;
+ if (this.numberOfBits != that.numberOfBits)
+ return false;
+ if (this.scanlineStride != that.scanlineStride)
+ return false;
+ if (this.dataBitOffset != that.dataBitOffset)
+ return false;
+ return true;
+ }
+
+ /**
+ * Returns a hash code for this <code>MultiPixelPackedSampleModel</code>.
+ *
+ * @return A hash code.
+ */
+ public int hashCode()
+ {
+ // this hash code won't match Sun's, but that shouldn't matter...
+ int result = 193;
+ result = 37 * result + dataType;
+ result = 37 * result + width;
+ result = 37 * result + height;
+ result = 37 * result + numberOfBits;
+ result = 37 * result + scanlineStride;
+ result = 37 * result + dataBitOffset;
+ return result;
+ }
+
+ /**
* Creates a String with some information about this SampleModel.
* @return A String describing this SampleModel.
* @see java.lang.Object#toString()
diff --git a/java/awt/image/Raster.java b/java/awt/image/Raster.java
index 4af958a17..160f8be8b 100644
--- a/java/awt/image/Raster.java
+++ b/java/awt/image/Raster.java
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000, 2002, 2003 Free Software Foundation
+/* Copyright (C) 2000, 2002, 2003, 2006, Free Software Foundation
This file is part of GNU Classpath.
@@ -41,39 +41,80 @@ import java.awt.Point;
import java.awt.Rectangle;
/**
+ * A rectangular collection of pixels composed from a {@link DataBuffer} which
+ * stores the pixel values, and a {@link SampleModel} which is used to retrieve
+ * the pixel values.
+ *
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
public class Raster
{
+ /** The sample model used to access the pixel values. */
protected SampleModel sampleModel;
+
+ /** The data buffer used to store the pixel values. */
protected DataBuffer dataBuffer;
+
+ /** The x-coordinate of the top left corner of the raster. */
protected int minX;
+
+ /** The y-coordinate of the top left corner of the raster. */
protected int minY;
+
+ /** The width of the raster. */
protected int width;
+
+ /** The height of the raster. */
protected int height;
+
protected int sampleModelTranslateX;
+
protected int sampleModelTranslateY;
+
+ /** The number of bands. */
protected int numBands;
+
protected int numDataElements;
+
+ /** The raster's parent. */
protected Raster parent;
+ /**
+ * Creates a new raster.
+ *
+ * @param sampleModel the sample model.
+ * @param origin the origin.
+ */
protected Raster(SampleModel sampleModel, Point origin)
{
this(sampleModel, sampleModel.createDataBuffer(), origin);
}
+ /**
+ * Creates a new raster.
+ *
+ * @param sampleModel the sample model.
+ * @param dataBuffer the data buffer.
+ * @param origin the origin.
+ */
protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
- Point origin)
+ Point origin)
{
- this(sampleModel, dataBuffer,
- new Rectangle(origin.x, origin.y,
- sampleModel.getWidth(), sampleModel.getHeight()),
- origin, null);
+ this(sampleModel, dataBuffer, new Rectangle(origin.x, origin.y,
+ sampleModel.getWidth(), sampleModel.getHeight()), origin, null);
}
+ /**
+ * Creates a new raster.
+ *
+ * @param sampleModel the sample model.
+ * @param dataBuffer the data buffer.
+ * @param aRegion the raster's bounds.
+ * @param sampleModelTranslate the translation (<code>null</code> permitted).
+ * @param parent the raster's parent.
+ */
protected Raster(SampleModel sampleModel, DataBuffer dataBuffer,
- Rectangle aRegion,
- Point sampleModelTranslate, Raster parent)
+ Rectangle aRegion, Point sampleModelTranslate, Raster parent)
{
this.sampleModel = sampleModel;
this.dataBuffer = dataBuffer;
@@ -95,70 +136,127 @@ public class Raster
this.parent = parent;
}
+ /**
+ * Creates an interleaved raster using the specified data type.
+ *
+ * @param dataType the data type.
+ * @param w the width.
+ * @param h the height.
+ * @param bands the number of bands.
+ * @param location
+ *
+ * @return The new raster.
+ */
public static WritableRaster createInterleavedRaster(int dataType,
- int w, int h,
- int bands,
- Point location)
+ int w, int h, int bands, Point location)
{
int[] bandOffsets = new int[bands];
// TODO: Maybe not generate this every time.
- for (int b=0; b<bands; b++) bandOffsets[b] = b;
+ for (int b = 0; b < bands; b++)
+ bandOffsets[b] = b;
- int scanlineStride = bands*w;
+ int scanlineStride = bands * w;
return createInterleavedRaster(dataType, w, h, scanlineStride, bands,
- bandOffsets, location);
+ bandOffsets, location);
}
- public static WritableRaster createInterleavedRaster(int dataType,
- int w, int h,
- int scanlineStride,
- int pixelStride,
- int[] bandOffsets,
- Point location)
- {
- SampleModel sm = new ComponentSampleModel(dataType,
- w, h,
- pixelStride,
- scanlineStride,
- bandOffsets);
+ /**
+ * Creates an interleaved raster.
+ *
+ * @param dataType the data type.
+ * @param w the width.
+ * @param h the height.
+ * @param scanlineStride the number of data elements from a sample on one
+ * row to the corresponding sample on the next row.
+ * @param pixelStride the number of elements from a sample in one pixel to
+ * the corresponding sample in the next pixel.
+ * @param bandOffsets the band offsets.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createInterleavedRaster(int dataType,
+ int w, int h, int scanlineStride, int pixelStride, int[] bandOffsets,
+ Point location)
+ {
+ SampleModel sm = new ComponentSampleModel(dataType, w, h, pixelStride,
+ scanlineStride, bandOffsets);
return createWritableRaster(sm, location);
}
- public static WritableRaster createBandedRaster(int dataType,
- int w, int h, int bands,
- Point location)
+ /**
+ * Creates a new banded raster.
+ *
+ * @param dataType the data type.
+ * @param w the width.
+ * @param h the height.
+ * @param bands the number of bands.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createBandedRaster(int dataType, int w, int h,
+ int bands, Point location)
{
SampleModel sm = new BandedSampleModel(dataType, w, h, bands);
return createWritableRaster(sm, location);
}
- public static WritableRaster createBandedRaster(int dataType,
- int w, int h,
- int scanlineStride,
- int[] bankIndices,
- int[] bandOffsets,
- Point location)
+ /**
+ * Creates a new banded raster.
+ *
+ * @param dataType the data type.
+ * @param w the width.
+ * @param h the height.
+ * @param scanlineStride the number of data elements from a sample on one
+ * row to the corresponding sample on the next row.
+ * @param bankIndices the index for each bank.
+ * @param bandOffsets the offset for each band.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createBandedRaster(int dataType, int w, int h,
+ int scanlineStride, int[] bankIndices, int[] bandOffsets, Point location)
{
SampleModel sm = new BandedSampleModel(dataType, w, h, scanlineStride,
- bankIndices, bandOffsets);
+ bankIndices, bandOffsets);
return createWritableRaster(sm, location);
}
- public static WritableRaster createPackedRaster(int dataType,
- int w, int h,
- int[] bandMasks,
- Point location)
+ /**
+ * Creates a new packed raster.
+ *
+ * @param dataType the data type.
+ * @param w the width.
+ * @param h the height.
+ * @param bandMasks the bit mask for each band.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createPackedRaster(int dataType, int w, int h,
+ int[] bandMasks, Point location)
{
- SampleModel sm = new SinglePixelPackedSampleModel(dataType,
- w, h,
- bandMasks);
+ SampleModel sm = new SinglePixelPackedSampleModel(dataType, w, h,
+ bandMasks);
return createWritableRaster(sm, location);
}
+ /**
+ * Creates a new raster.
+ *
+ * @param dataType the data type.
+ * @param w the width.
+ * @param h the height.
+ * @param bands the number of bands.
+ * @param bitsPerBand the number of bits per band.
+ * @param location
+ *
+ * @return The new raster.
+ */
public static WritableRaster createPackedRaster(int dataType,
- int w, int h,
- int bands, int bitsPerBand,
- Point location)
+ int w, int h, int bands, int bitsPerBand, Point location)
{
if (bands <= 0 || (bands * bitsPerBand > getTypeBits(dataType)))
throw new IllegalArgumentException();
@@ -166,135 +264,238 @@ public class Raster
SampleModel sm;
if (bands == 1)
- sm = new MultiPixelPackedSampleModel(dataType, w, h, bitsPerBand);
+ sm = new MultiPixelPackedSampleModel(dataType, w, h, bitsPerBand);
else
{
- int[] bandMasks = new int[bands];
- int mask = 0x1;
- for (int bits = bitsPerBand; --bits != 0;)
- mask = (mask << 1) | 0x1;
- for (int i = 0; i < bands; i++)
- {
- bandMasks[i] = mask;
- mask <<= bitsPerBand;
- }
-
- sm = new SinglePixelPackedSampleModel(dataType, w, h, bandMasks);
+ int[] bandMasks = new int[bands];
+ int mask = 0x1;
+ for (int bits = bitsPerBand; --bits != 0;)
+ mask = (mask << 1) | 0x1;
+ for (int i = 0; i < bands; i++)
+ {
+ bandMasks[i] = mask;
+ mask <<= bitsPerBand;
+ }
+
+ sm = new SinglePixelPackedSampleModel(dataType, w, h, bandMasks);
}
return createWritableRaster(sm, location);
}
- public static WritableRaster
- createInterleavedRaster(DataBuffer dataBuffer, int w, int h,
- int scanlineStride, int pixelStride,
- int[] bandOffsets, Point location)
+ /**
+ * Creates a new interleaved raster.
+ *
+ * @param dataBuffer the data buffer.
+ * @param w the width.
+ * @param h the height.
+ * @param scanlineStride the number of data elements from a sample on one
+ * row to the corresponding sample on the next row.
+ * @param pixelStride the number of elements from a sample in one pixel to
+ * the corresponding sample in the next pixel.
+ * @param bandOffsets the offset for each band.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createInterleavedRaster(DataBuffer dataBuffer,
+ int w, int h, int scanlineStride, int pixelStride, int[] bandOffsets,
+ Point location)
{
SampleModel sm = new ComponentSampleModel(dataBuffer.getDataType(),
- w, h,
- scanlineStride,
- pixelStride,
- bandOffsets);
+ w, h, scanlineStride, pixelStride, bandOffsets);
return createWritableRaster(sm, dataBuffer, location);
}
- public static
- WritableRaster createBandedRaster(DataBuffer dataBuffer,
- int w, int h,
- int scanlineStride,
- int[] bankIndices,
- int[] bandOffsets,
- Point location)
+ /**
+ * Creates a new banded raster.
+ *
+ * @param dataBuffer the data buffer.
+ * @param w the width.
+ * @param h the height.
+ * @param scanlineStride the number of data elements from a sample on one
+ * row to the corresponding sample on the next row.
+ * @param bankIndices the index for each bank.
+ * @param bandOffsets the band offsets.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createBandedRaster(DataBuffer dataBuffer,
+ int w, int h, int scanlineStride, int[] bankIndices, int[] bandOffsets,
+ Point location)
{
SampleModel sm = new BandedSampleModel(dataBuffer.getDataType(),
- w, h, scanlineStride,
- bankIndices, bandOffsets);
+ w, h, scanlineStride, bankIndices, bandOffsets);
return createWritableRaster(sm, dataBuffer, location);
}
- public static WritableRaster
- createPackedRaster(DataBuffer dataBuffer,
- int w, int h,
- int scanlineStride,
- int[] bandMasks,
- Point location)
+ /**
+ * Creates a new packed raster.
+ *
+ * @param dataBuffer the data buffer.
+ * @param w the width.
+ * @param h the height.
+ * @param scanlineStride the number of data elements from a sample on one
+ * row to the corresponding sample on the next row.
+ * @param bandMasks the bit mask for each band.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createPackedRaster(DataBuffer dataBuffer,
+ int w, int h, int scanlineStride, int[] bandMasks, Point location)
{
- SampleModel sm =
- new SinglePixelPackedSampleModel(dataBuffer.getDataType(),
- w, h,
- scanlineStride,
- bandMasks);
+ SampleModel sm = new SinglePixelPackedSampleModel(dataBuffer.getDataType(),
+ w, h, scanlineStride, bandMasks);
return createWritableRaster(sm, dataBuffer, location);
}
- public static WritableRaster
- createPackedRaster(DataBuffer dataBuffer,
- int w, int h,
- int bitsPerPixel,
- Point location)
- {
- SampleModel sm =
- new MultiPixelPackedSampleModel(dataBuffer.getDataType(),
- w, h,
- bitsPerPixel);
+ /**
+ * Creates a new packed raster.
+ *
+ * @param dataBuffer the data buffer.
+ * @param w the width.
+ * @param h the height.
+ * @param bitsPerPixel the number of bits per pixel.
+ * @param location
+ *
+ * @return The new raster.
+ */
+ public static WritableRaster createPackedRaster(DataBuffer dataBuffer,
+ int w, int h, int bitsPerPixel, Point location)
+ {
+ SampleModel sm = new MultiPixelPackedSampleModel(dataBuffer.getDataType(),
+ w, h, bitsPerPixel);
return createWritableRaster(sm, dataBuffer, location);
}
+ /**
+ * Creates a new raster.
+ *
+ * @param sm the sample model.
+ * @param db the data buffer.
+ * @param location
+ *
+ * @return The new raster.
+ */
public static Raster createRaster(SampleModel sm, DataBuffer db,
- Point location)
+ Point location)
{
return new Raster(sm, db, location);
}
+ /**
+ * Creates a new writable raster.
+ *
+ * @param sm the sample model.
+ * @param location
+ *
+ * @return The new writable raster.
+ */
public static WritableRaster createWritableRaster(SampleModel sm,
- Point location)
+ Point location)
{
return new WritableRaster(sm, location);
}
+ /**
+ * Creates a new writable raster.
+ *
+ * @param sm the sample model.
+ * @param db the data buffer.
+ * @param location
+ *
+ * @return The new writable raster.
+ */
public static WritableRaster createWritableRaster(SampleModel sm,
- DataBuffer db,
- Point location)
+ DataBuffer db, Point location)
{
return new WritableRaster(sm, db, location);
}
+ /**
+ * Returns the raster's parent.
+ *
+ * @return The raster's parent.
+ */
public Raster getParent()
{
return parent;
}
+ /**
+ * Returns the x-translation.
+ *
+ * @return The x-translation.
+ */
public final int getSampleModelTranslateX()
{
return sampleModelTranslateX;
}
+ /**
+ * Returns the y-translation.
+ *
+ * @return The y-translation.
+ */
public final int getSampleModelTranslateY()
{
return sampleModelTranslateY;
}
+ /**
+ * Creates a new writable raster that is compatible with this raster.
+ *
+ * @return A new writable raster.
+ */
public WritableRaster createCompatibleWritableRaster()
{
return new WritableRaster(getSampleModel(), new Point(minX, minY));
}
+ /**
+ * Creates a new writable raster that is compatible with this raster.
+ *
+ * @param w the width.
+ * @param h the height.
+ *
+ * @return A new writable raster.
+ */
public WritableRaster createCompatibleWritableRaster(int w, int h)
{
return createCompatibleWritableRaster(minX, minY, w, h);
}
+ /**
+ * Creates a new writable raster that is compatible with this raster, with
+ * the specified bounds.
+ *
+ * @param rect the raster bounds.
+ *
+ * @return A new writable raster.
+ */
public WritableRaster createCompatibleWritableRaster(Rectangle rect)
{
return createCompatibleWritableRaster(rect.x, rect.y,
- rect.width, rect.height);
+ rect.width, rect.height);
}
+ /**
+ * Creates a new writable raster that is compatible with this raster, with
+ * the specified bounds.
+ *
+ * @param x the x-coordinate of the top-left corner of the raster.
+ * @param y the y-coordinate of the top-left corner of the raster.
+ * @param w the raster width.
+ * @param h the raster height.
+ *
+ * @return A new writable raster.
+ */
public WritableRaster createCompatibleWritableRaster(int x, int y,
- int w, int h)
+ int w, int h)
{
SampleModel sm = getSampleModel().createCompatibleSampleModel(w, h);
- return new WritableRaster(sm, sm.createDataBuffer(),
- new Point(x, y));
+ return new WritableRaster(sm, sm.createDataBuffer(), new Point(x, y));
}
public Raster createTranslatedChild(int childMinX, int childMinY) {
@@ -302,15 +503,13 @@ public class Raster
int tcy = sampleModelTranslateY - minY + childMinY;
return new Raster(sampleModel, dataBuffer,
- new Rectangle(childMinX, childMinY,
- width, height),
- new Point(tcx, tcy),
- this);
+ new Rectangle(childMinX, childMinY, width, height),
+ new Point(tcx, tcy), this);
}
public Raster createChild(int parentX, int parentY, int width,
- int height, int childMinX, int childMinY,
- int[] bandList)
+ int height, int childMinX, int childMinY,
+ int[] bandList)
{
/* FIXME: Throw RasterFormatException if child bounds extends
beyond the bounds of this raster. */
@@ -343,38 +542,67 @@ public class Raster
*/
return new Raster(sm, dataBuffer,
- new Rectangle(childMinX, childMinY,
- width, height),
- new Point(sampleModelTranslateX+childMinX-parentX,
- sampleModelTranslateY+childMinY-parentY),
- this);
+ new Rectangle(childMinX, childMinY, width, height),
+ new Point(sampleModelTranslateX + childMinX - parentX,
+ sampleModelTranslateY + childMinY - parentY),
+ this);
}
+ /**
+ * Returns a new rectangle containing the bounds of this raster.
+ *
+ * @return A new rectangle containing the bounds of this raster.
+ */
public Rectangle getBounds()
{
return new Rectangle(minX, minY, width, height);
}
+ /**
+ * Returns the x-coordinate of the top left corner of the raster.
+ *
+ * @return The x-coordinate of the top left corner of the raster.
+ */
public final int getMinX()
{
return minX;
}
+ /**
+ * Returns the t-coordinate of the top left corner of the raster.
+ *
+ * @return The t-coordinate of the top left corner of the raster.
+ */
public final int getMinY()
{
return minY;
}
+ /**
+ * Returns the width of the raster.
+ *
+ * @return The width of the raster.
+ */
public final int getWidth()
{
return width;
}
+ /**
+ * Returns the height of the raster.
+ *
+ * @return The height of the raster.
+ */
public final int getHeight()
{
return height;
}
+ /**
+ * Returns the number of bands for this raster.
+ *
+ * @return The number of bands.
+ */
public final int getNumBands()
{
return numBands;
@@ -384,17 +612,34 @@ public class Raster
{
return numDataElements;
}
-
+
+ /**
+ * Returns the transfer type for the raster (this is determined by the
+ * raster's sample model).
+ *
+ * @return The transfer type.
+ */
public final int getTransferType()
{
return sampleModel.getTransferType();
}
+ /**
+ * Returns the data buffer that stores the pixel data for this raster.
+ *
+ * @return The data buffer.
+ */
public DataBuffer getDataBuffer()
{
return dataBuffer;
}
+ /**
+ * Returns the sample model that accesses the data buffer (to extract pixel
+ * data) for this raster.
+ *
+ * @return The sample model.
+ */
public SampleModel getSampleModel()
{
return sampleModel;
@@ -402,112 +647,275 @@ public class Raster
public Object getDataElements(int x, int y, Object outData)
{
- return sampleModel.getDataElements(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- outData, dataBuffer);
+ return sampleModel.getDataElements(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, outData, dataBuffer);
}
- public Object getDataElements(int x, int y, int w, int h,
- Object outData)
+ public Object getDataElements(int x, int y, int w, int h, Object outData)
{
- return sampleModel.getDataElements(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- w, h, outData, dataBuffer);
+ return sampleModel.getDataElements(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, outData, dataBuffer);
}
+ /**
+ * Returns an array containing the samples for the pixel at (x, y) in the
+ * raster. If <code>iArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of
+ * this function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The pixel sample values.
+ */
public int[] getPixel(int x, int y, int[] iArray)
{
- return sampleModel.getPixel(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- iArray, dataBuffer);
+ return sampleModel.getPixel(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, iArray, dataBuffer);
}
+ /**
+ * Returns an array containing the samples for the pixel at (x, y) in the
+ * raster. If <code>fArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of
+ * this function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param fArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The pixel sample values.
+ */
public float[] getPixel(int x, int y, float[] fArray)
{
- return sampleModel.getPixel(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- fArray, dataBuffer);
+ return sampleModel.getPixel(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, fArray, dataBuffer);
}
+ /**
+ * Returns an array containing the samples for the pixel at (x, y) in the
+ * raster. If <code>dArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of
+ * this function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param dArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The pixel sample values.
+ */
public double[] getPixel(int x, int y, double[] dArray)
{
- return sampleModel.getPixel(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- dArray, dataBuffer);
+ return sampleModel.getPixel(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, dArray, dataBuffer);
}
+ /**
+ * Returns an array containing the samples for the pixels in the region
+ * specified by (x, y, w, h) in the raster. The array is ordered by pixels
+ * (that is, all the samples for the first pixel are grouped together,
+ * followed by all the samples for the second pixel, and so on).
+ * If <code>iArray</code> is not <code>null</code>, it will be populated
+ * with the sample values and returned as the result of this function (this
+ * avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The pixel sample values.
+ */
public int[] getPixels(int x, int y, int w, int h, int[] iArray)
{
- return sampleModel.getPixels(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- w, h, iArray, dataBuffer);
+ return sampleModel.getPixels(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, iArray, dataBuffer);
}
- public float[] getPixels(int x, int y, int w, int h,
- float[] fArray)
+ /**
+ * Returns an array containing the samples for the pixels in the region
+ * specified by (x, y, w, h) in the raster. The array is ordered by pixels
+ * (that is, all the samples for the first pixel are grouped together,
+ * followed by all the samples for the second pixel, and so on).
+ * If <code>fArray</code> is not <code>null</code>, it will be populated
+ * with the sample values and returned as the result of this function (this
+ * avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param fArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The pixel sample values.
+ */
+ public float[] getPixels(int x, int y, int w, int h, float[] fArray)
{
- return sampleModel.getPixels(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- w, h, fArray, dataBuffer);
+ return sampleModel.getPixels(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, fArray, dataBuffer);
}
- public double[] getPixels(int x, int y, int w, int h,
- double[] dArray)
+ /**
+ * Returns an array containing the samples for the pixels in the region
+ * specified by (x, y, w, h) in the raster. The array is ordered by pixels
+ * (that is, all the samples for the first pixel are grouped together,
+ * followed by all the samples for the second pixel, and so on).
+ * If <code>dArray</code> is not <code>null</code>, it will be populated
+ * with the sample values and returned as the result of this function (this
+ * avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param dArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The pixel sample values.
+ */
+ public double[] getPixels(int x, int y, int w, int h, double[] dArray)
{
- return sampleModel.getPixels(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- w, h, dArray, dataBuffer);
+ return sampleModel.getPixels(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, dArray, dataBuffer);
}
+ /**
+ * Returns the sample value for the pixel at (x, y) in the raster.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ *
+ * @return The sample value.
+ */
public int getSample(int x, int y, int b)
{
- return sampleModel.getSample(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- b, dataBuffer);
+ return sampleModel.getSample(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, b, dataBuffer);
}
+ /**
+ * Returns the sample value for the pixel at (x, y) in the raster.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ *
+ * @return The sample value.
+ *
+ * @see #getSample(int, int, int)
+ */
public float getSampleFloat(int x, int y, int b)
{
- return sampleModel.getSampleFloat(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- b, dataBuffer);
+ return sampleModel.getSampleFloat(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, b, dataBuffer);
}
+ /**
+ * Returns the sample value for the pixel at (x, y) in the raster.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ *
+ * @return The sample value.
+ *
+ * @see #getSample(int, int, int)
+ */
public double getSampleDouble(int x, int y, int b)
{
- return sampleModel.getSampleDouble(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- b, dataBuffer);
+ return sampleModel.getSampleDouble(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, b, dataBuffer);
}
+ /**
+ * Returns an array containing the samples from one band for the pixels in
+ * the region specified by (x, y, w, h) in the raster. If
+ * <code>iArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The sample values.
+ */
public int[] getSamples(int x, int y, int w, int h, int b,
- int[] iArray)
+ int[] iArray)
{
- return sampleModel.getSamples(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- w, h, b, iArray, dataBuffer);
+ return sampleModel.getSamples(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, b, iArray, dataBuffer);
}
- public float[] getSamples(int x, int y, int w, int h, int b,
- float[] fArray)
- {
- return sampleModel.getSamples(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- w, h, b, fArray, dataBuffer);
+ /**
+ * Returns an array containing the samples from one band for the pixels in
+ * the region specified by (x, y, w, h) in the raster. If
+ * <code>fArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param fArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The sample values.
+ */
+ public float[] getSamples(int x, int y, int w, int h, int b, float[] fArray)
+ {
+ return sampleModel.getSamples(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, b, fArray, dataBuffer);
}
- public double[] getSamples(int x, int y, int w, int h, int b,
- double[] dArray)
+ /**
+ * Returns an array containing the samples from one band for the pixels in
+ * the region specified by (x, y, w, h) in the raster. If
+ * <code>dArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param dArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ *
+ * @return The sample values.
+ */
+ public double[] getSamples(int x, int y, int w, int h, int b,
+ double[] dArray)
{
- return sampleModel.getSamples(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- w, h, b, dArray, dataBuffer);
+ return sampleModel.getSamples(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, b, dArray, dataBuffer);
}
/**
- * Create a String representing the stat of this Raster.
+ * Create a String representing the state of this Raster.
+ *
* @return A String representing the stat of this Raster.
- * @see java.lang.Object#toString()
*/
public String toString()
{
@@ -524,23 +932,39 @@ public class Raster
return result.toString();
}
- // Map from datatype to bits
+ /**
+ * Returns the number of bits used to represent the specified data type.
+ * Valid types are:
+ * <ul>
+ * <li>{@link DataBuffer#TYPE_BYTE};</li>
+ * <li>{@link DataBuffer#TYPE_USHORT};</li>
+ * <li>{@link DataBuffer#TYPE_SHORT};</li>
+ * <li>{@link DataBuffer#TYPE_INT};</li>
+ * <li>{@link DataBuffer#TYPE_FLOAT};</li>
+ * <li>{@link DataBuffer#TYPE_DOUBLE};</li>
+ * </ul>
+ * This method returns 0 for invalid data types.
+ *
+ * @param dataType the data type.
+ *
+ * @return The number of bits used to represent the specified data type.
+ */
private static int getTypeBits(int dataType)
{
switch (dataType)
{
case DataBuffer.TYPE_BYTE:
- return 8;
+ return 8;
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_SHORT:
- return 16;
+ return 16;
case DataBuffer.TYPE_INT:
case DataBuffer.TYPE_FLOAT:
- return 32;
+ return 32;
case DataBuffer.TYPE_DOUBLE:
- return 64;
+ return 64;
default:
- return 0;
+ return 0;
}
}
}
diff --git a/java/awt/image/RasterOp.java b/java/awt/image/RasterOp.java
index e081ca3d2..656370e8b 100644
--- a/java/awt/image/RasterOp.java
+++ b/java/awt/image/RasterOp.java
@@ -1,5 +1,5 @@
/* RasterOp.java --
- Copyright (C) 2000, 2002, 2004, 2005 Free Software Foundation
+ Copyright (C) 2000, 2002, 2004, 2005, 2006, Free Software Foundation
This file is part of GNU Classpath.
@@ -42,16 +42,64 @@ import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
+/**
+ * An operation that is performed on one raster (the source) producing a new
+ * raster (the destination).
+ */
public interface RasterOp
{
+ /**
+ * Performs an operation on the source raster, returning the result in a
+ * writable raster. If <code>dest</code> is <code>null</code>, a new
+ * <code>WritableRaster</code> will be created by calling the
+ * {@link #createCompatibleDestRaster(Raster)} method. If <code>dest</code>
+ * is not <code>null</code>, the result is written to <code>dest</code> then
+ * returned (this avoids creating a new <code>WritableRaster</code> each
+ * time this method is called).
+ *
+ * @param src the source raster.
+ * @param dest the destination raster (<code>null</code> permitted).
+ *
+ * @return The filtered raster.
+ */
WritableRaster filter(Raster src, WritableRaster dest);
+ /**
+ * Returns the bounds of the destination raster on the basis of this
+ * <code>RasterOp</code> being applied to the specified source raster.
+ *
+ * @param src the source raster.
+ *
+ * @return The destination bounds.
+ */
Rectangle2D getBounds2D(Raster src);
+ /**
+ * Returns a raster that can be used by this <code>RasterOp</code> as the
+ * destination raster when operating on the specified source raster.
+ *
+ * @param src the source raster.
+ *
+ * @return A new writable raster that can be used as the destination raster.
+ */
WritableRaster createCompatibleDestRaster(Raster src);
+ /**
+ * Returns the point on the destination raster that corresponds to the given
+ * point on the source raster.
+ *
+ * @param srcPoint the source point.
+ * @param destPoint the destination point (<code>null</code> permitted).
+ *
+ * @return The destination point.
+ */
Point2D getPoint2D(Point2D srcPoint, Point2D destPoint);
+ /**
+ * Returns the rendering hints for this operation.
+ *
+ * @return The rendering hints.
+ */
RenderingHints getRenderingHints();
}
diff --git a/java/awt/image/SampleModel.java b/java/awt/image/SampleModel.java
index 6e3fd4069..cb352bb4d 100644
--- a/java/awt/image/SampleModel.java
+++ b/java/awt/image/SampleModel.java
@@ -37,6 +37,9 @@ exception statement from your version. */
package java.awt.image;
/**
+ * A <code>SampleModel</code> is used to access pixel data from a
+ * {@link DataBuffer}. This is used by the {@link Raster} class.
+ *
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
public abstract class SampleModel
@@ -100,16 +103,37 @@ public abstract class SampleModel
this.numBands = numBands;
}
+ /**
+ * Returns the width of the pixel data accessible via this
+ * <code>SampleModel</code>.
+ *
+ * @return The width.
+ *
+ * @see #getHeight()
+ */
public final int getWidth()
{
return width;
}
+ /**
+ * Returns the height of the pixel data accessible via this
+ * <code>SampleModel</code>.
+ *
+ * @return The height.
+ *
+ * @see #getWidth()
+ */
public final int getHeight()
{
return height;
}
+ /**
+ * Returns the number of bands for this <code>SampleModel</code>.
+ *
+ * @return The number of bands.
+ */
public final int getNumBands()
{
return numBands;
@@ -117,6 +141,12 @@ public abstract class SampleModel
public abstract int getNumDataElements();
+ /**
+ * Returns the type of the {@link DataBuffer} that this
+ * <code>SampleModel</code> accesses.
+ *
+ * @return The data buffer type.
+ */
public final int getDataType()
{
return dataType;
@@ -128,6 +158,22 @@ public abstract class SampleModel
return dataType;
}
+ /**
+ * Returns an array containing the samples for the pixel at (x, y) in the
+ * specified data buffer. If <code>iArray</code> is not <code>null</code>,
+ * it will be populated with the sample values and returned as the result of
+ * this function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
{
if (iArray == null)
@@ -234,6 +280,22 @@ public abstract class SampleModel
}
}
+ /**
+ * Returns an array containing the samples for the pixel at (x, y) in the
+ * specified data buffer. If <code>fArray</code> is not <code>null</code>,
+ * it will be populated with the sample values and returned as the result of
+ * this function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param fArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public float[] getPixel(int x, int y, float[] fArray, DataBuffer data)
{
if (fArray == null)
@@ -246,6 +308,22 @@ public abstract class SampleModel
return fArray;
}
+ /**
+ * Returns an array containing the samples for the pixel at (x, y) in the
+ * specified data buffer. If <code>dArray</code> is not <code>null</code>,
+ * it will be populated with the sample values and returned as the result of
+ * this function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param dArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public double[] getPixel(int x, int y, double[] dArray, DataBuffer data) {
if (dArray == null)
dArray = new double[numBands];
@@ -256,8 +334,27 @@ public abstract class SampleModel
return dArray;
}
- /* FIXME: Should it return a banded or pixel interleaved array of
- samples? (Assume interleaved.) */
+ /**
+ * Returns an array containing the samples for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on). If <code>iArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public int[] getPixels(int x, int y, int w, int h, int[] iArray,
DataBuffer data)
{
@@ -278,8 +375,27 @@ public abstract class SampleModel
return iArray;
}
- /* FIXME: Should it return a banded or pixel interleaved array of
- samples? (Assume interleaved.) */
+ /**
+ * Returns an array containing the samples for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on). If <code>fArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param fArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public float[] getPixels(int x, int y, int w, int h, float[] fArray,
DataBuffer data)
{
@@ -299,8 +415,27 @@ public abstract class SampleModel
return fArray;
}
- /* FIXME: Should it return a banded or pixel interleaved array of
- samples? (Assume interleaved.) */
+ /**
+ * Returns an array containing the samples for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on). If <code>dArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param dArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public double[] getPixels(int x, int y, int w, int h, double[] dArray,
DataBuffer data)
{
@@ -321,18 +456,85 @@ public abstract class SampleModel
return dArray;
}
+ /**
+ * Returns the sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public abstract int getSample(int x, int y, int b, DataBuffer data);
+ /**
+ * Returns the sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ *
+ * @see #getSample(int, int, int, DataBuffer)
+ */
public float getSampleFloat(int x, int y, int b, DataBuffer data)
{
return getSample(x, y, b, data);
}
+ /**
+ * Returns the sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ *
+ * @see #getSample(int, int, int, DataBuffer)
+ */
public double getSampleDouble(int x, int y, int b, DataBuffer data)
{
return getSampleFloat(x, y, b, data);
}
+ /**
+ * Returns an array containing the samples from one band for the pixels in
+ * the region specified by (x, y, w, h) in the specified data buffer. If
+ * <code>iArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public int[] getSamples(int x, int y, int w, int h, int b,
int[] iArray, DataBuffer data)
{
@@ -350,6 +552,27 @@ public abstract class SampleModel
return iArray;
}
+ /**
+ * Returns an array containing the samples from one band for the pixels in
+ * the region specified by (x, y, w, h) in the specified data buffer. If
+ * <code>fArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param fArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public float[] getSamples(int x, int y, int w, int h, int b,
float[] fArray, DataBuffer data)
{
@@ -367,6 +590,27 @@ public abstract class SampleModel
return fArray;
}
+ /**
+ * Returns an array containing the samples from one band for the pixels in
+ * the region specified by (x, y, w, h) in the specified data buffer. If
+ * <code>dArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param dArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public double[] getSamples(int x, int y, int w, int h, int b,
double[] dArray, DataBuffer data)
{
@@ -384,24 +628,77 @@ public abstract class SampleModel
return dArray;
}
+ /**
+ * Sets the samples for the pixel at (x, y) in the specified data buffer to
+ * the specified values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
public void setPixel(int x, int y, int[] iArray, DataBuffer data)
{
for (int b = 0; b < numBands; b++)
setSample(x, y, b, iArray[b], data);
}
+ /**
+ * Sets the samples for the pixel at (x, y) in the specified data buffer to
+ * the specified values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param fArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>fArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
public void setPixel(int x, int y, float[] fArray, DataBuffer data)
{
for (int b = 0; b < numBands; b++)
setSample(x, y, b, fArray[b], data);
}
+ /**
+ * Sets the samples for the pixel at (x, y) in the specified data buffer to
+ * the specified values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param dArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>dArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
public void setPixel(int x, int y, double[] dArray, DataBuffer data)
{
for (int b = 0; b < numBands; b++)
setSample(x, y, b, dArray[b], data);
}
+ /**
+ * Sets the sample values for the pixels in the region specified by
+ * (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param iArray the pixel sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
public void setPixels(int x, int y, int w, int h, int[] iArray,
DataBuffer data)
{
@@ -418,6 +715,23 @@ public abstract class SampleModel
}
}
+ /**
+ * Sets the sample values for the pixels in the region specified by
+ * (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param fArray the pixel sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>fArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
public void setPixels(int x, int y, int w, int h, float[] fArray,
DataBuffer data)
{
@@ -434,6 +748,23 @@ public abstract class SampleModel
}
}
+ /**
+ * Sets the sample values for the pixels in the region specified by
+ * (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param dArray the pixel sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>dArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
public void setPixels(int x, int y, int w, int h, double[] dArray,
DataBuffer data)
{
@@ -450,21 +781,76 @@ public abstract class SampleModel
}
}
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the
+ * specified data buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public abstract void setSample(int x, int y, int b, int s,
DataBuffer data);
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the
+ * specified data buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public void setSample(int x, int y, int b, float s,
DataBuffer data)
{
setSample(x, y, b, (int) s, data);
}
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the
+ * specified data buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public void setSample(int x, int y, int b, double s,
DataBuffer data)
{
setSample(x, y, b, (float) s, data);
}
+ /**
+ * Sets the sample values for one band for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer.
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param iArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
public void setSamples(int x, int y, int w, int h, int b,
int[] iArray, DataBuffer data)
{
@@ -475,6 +861,22 @@ public abstract class SampleModel
setSample(xx, yy, b, iArray[inOffset++], data);
}
+ /**
+ * Sets the sample values for one band for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer.
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param fArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
public void setSamples(int x, int y, int w, int h, int b,
float[] fArray, DataBuffer data)
{
@@ -486,6 +888,22 @@ public abstract class SampleModel
}
+ /**
+ * Sets the sample values for one band for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer.
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param dArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
public void setSamples(int x, int y, int w, int h, int b,
double[] dArray, DataBuffer data) {
int size = w * h;
@@ -495,6 +913,15 @@ public abstract class SampleModel
setSample(xx, yy, b, dArray[inOffset++], data);
}
+ /**
+ * Creates a new <code>SampleModel</code> that is compatible with this
+ * model and has the specified width and height.
+ *
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ *
+ * @return The new sample model.
+ */
public abstract SampleModel createCompatibleSampleModel(int w, int h);
/**
@@ -510,9 +937,31 @@ public abstract class SampleModel
*/
public abstract SampleModel createSubsetSampleModel(int[] bands);
+ /**
+ * Creates a new {@link DataBuffer} of the correct type and size for this
+ * <code>SampleModel</code>.
+ *
+ * @return The data buffer.
+ */
public abstract DataBuffer createDataBuffer();
+ /**
+ * Returns an array containing the size (in bits) for each band accessed by
+ * the <code>SampleModel</code>.
+ *
+ * @return An array.
+ *
+ * @see #getSampleSize(int)
+ */
public abstract int[] getSampleSize();
+ /**
+ * Returns the size (in bits) of the samples for the specified band.
+ *
+ * @param band the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ *
+ * @return The sample size (in bits).
+ */
public abstract int getSampleSize(int band);
}
diff --git a/java/awt/image/ShortLookupTable.java b/java/awt/image/ShortLookupTable.java
index 5915a7939..858818cf2 100644
--- a/java/awt/image/ShortLookupTable.java
+++ b/java/awt/image/ShortLookupTable.java
@@ -1,5 +1,5 @@
/* ShortLookupTable.java -- Java class for a pixel translation table.
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -67,7 +67,13 @@ public class ShortLookupTable extends LookupTable
throws IllegalArgumentException
{
super(offset, data.length);
- this.data = data;
+
+ // tests show that Sun's implementation creates a new array to store the
+ // references from the incoming 'data' array - not sure why, but we'll
+ // match that behaviour just in case it matters...
+ this.data = new short[data.length][];
+ for (int i = 0; i < data.length; i++)
+ this.data[i] = data[i];
}
/**
@@ -77,17 +83,25 @@ public class ShortLookupTable extends LookupTable
* table. The same table is applied to all pixel components.
*
* @param offset Offset to be subtracted.
- * @param data Lookup table for all components.
+ * @param data Lookup table for all components (<code>null</code> not
+ * permitted).
* @exception IllegalArgumentException if offset &lt; 0.
*/
public ShortLookupTable(int offset, short[] data)
throws IllegalArgumentException
{
super(offset, 1);
+ if (data == null)
+ throw new NullPointerException("Null 'data' argument.");
this.data = new short[][] {data};
}
- /** Return the lookup tables. */
+ /**
+ * Return the lookup tables. This is a reference to the actual table, so
+ * modifying the contents of the returned array will modify the lookup table.
+ *
+ * @return The lookup table.
+ */
public final short[][] getTable()
{
return data;
@@ -117,11 +131,11 @@ public class ShortLookupTable extends LookupTable
dst = new int[src.length];
if (data.length == 1)
- for (int i=0; i < src.length; i++)
- dst[i] = data[0][src[i] - offset];
+ for (int i = 0; i < src.length; i++)
+ dst[i] = data[0][src[i] - offset];
else
- for (int i=0; i < src.length; i++)
- dst[i] = data[i][src[i] - offset];
+ for (int i = 0; i < src.length; i++)
+ dst[i] = data[i][src[i] - offset];
return dst;
}
@@ -142,6 +156,7 @@ public class ShortLookupTable extends LookupTable
* @param src Component values of a pixel.
* @param dst Destination array for values, or null.
* @return Translated values for the pixel.
+ *
*/
public short[] lookupPixel(short[] src, short[] dst)
throws ArrayIndexOutOfBoundsException
@@ -150,11 +165,11 @@ public class ShortLookupTable extends LookupTable
dst = new short[src.length];
if (data.length == 1)
- for (int i=0; i < src.length; i++)
- dst[i] = data[0][((int)src[i]) - offset];
+ for (int i = 0; i < src.length; i++)
+ dst[i] = data[0][((int) src[i]) - offset];
else
- for (int i=0; i < src.length; i++)
- dst[i] = data[i][((int)src[i]) - offset];
+ for (int i = 0; i < src.length; i++)
+ dst[i] = data[i][((int) src[i]) - offset];
return dst;
diff --git a/java/awt/image/SinglePixelPackedSampleModel.java b/java/awt/image/SinglePixelPackedSampleModel.java
index 6ccce753b..a37fc0bba 100644
--- a/java/awt/image/SinglePixelPackedSampleModel.java
+++ b/java/awt/image/SinglePixelPackedSampleModel.java
@@ -1,4 +1,4 @@
-/* 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.
@@ -36,10 +36,16 @@ exception statement from your version. */
package java.awt.image;
+import java.util.Arrays;
+
import gnu.java.awt.BitMaskExtent;
import gnu.java.awt.Buffers;
/**
+ * A <code>SampleModel</code> used when all samples are stored in a single
+ * data element in the {@link DataBuffer}, and each data element contains
+ * samples for one pixel only.
+ *
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
public class SinglePixelPackedSampleModel extends SampleModel
@@ -49,12 +55,32 @@ public class SinglePixelPackedSampleModel extends SampleModel
private int[] bitOffsets;
private int[] sampleSize;
+ /**
+ * Creates a new <code>SinglePixelPackedSampleModel</code>.
+ *
+ * @param dataType the data buffer type.
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ * @param bitMasks an array containing the bit mask used to extract the
+ * sample value for each band.
+ */
public SinglePixelPackedSampleModel(int dataType, int w, int h,
int[] bitMasks)
{
this(dataType, w, h, w, bitMasks);
}
+ /**
+ * Creates a new <code>SinglePixelPackedSampleModel</code>.
+ *
+ * @param dataType the data buffer type.
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ * @param scanlineStride the number of data elements between a pixel on one
+ * row and the corresponding pixel on the next row.
+ * @param bitMasks an array containing the bit mask used to extract the
+ * sample value for each band.
+ */
public SinglePixelPackedSampleModel(int dataType, int w, int h,
int scanlineStride, int[] bitMasks)
{
@@ -67,7 +93,8 @@ public class SinglePixelPackedSampleModel extends SampleModel
case DataBuffer.TYPE_INT:
break;
default:
- throw new IllegalArgumentException("SinglePixelPackedSampleModel unsupported dataType");
+ throw new IllegalArgumentException(
+ "SinglePixelPackedSampleModel unsupported dataType");
}
this.scanlineStride = scanlineStride;
@@ -77,19 +104,35 @@ public class SinglePixelPackedSampleModel extends SampleModel
sampleSize = new int[numBands];
BitMaskExtent extent = new BitMaskExtent();
- for (int b=0; b<numBands; b++)
+ for (int b = 0; b < numBands; b++)
{
- extent.setMask(bitMasks[b]);
- sampleSize[b] = extent.bitWidth;
- bitOffsets[b] = extent.leastSignificantBit;
+ // the mask is an unsigned integer
+ long mask = bitMasks[b] & 0xFFFFFFFFL;
+ extent.setMask(mask);
+ sampleSize[b] = extent.bitWidth;
+ bitOffsets[b] = extent.leastSignificantBit;
}
}
+ /**
+ * Returns the number of data elements.
+ *
+ * @return <code>1</code>.
+ */
public int getNumDataElements()
{
return 1;
}
+ /**
+ * Creates a new <code>SampleModel</code> that is compatible with this
+ * model and has the specified width and height.
+ *
+ * @param w the width (in pixels).
+ * @param h the height (in pixels).
+ *
+ * @return The new sample model.
+ */
public SampleModel createCompatibleSampleModel(int w, int h)
{
/* FIXME: We can avoid recalculation of bit offsets and sample
@@ -103,6 +146,8 @@ public class SinglePixelPackedSampleModel extends SampleModel
* Creates a DataBuffer for holding pixel data in the format and
* layout described by this SampleModel. The returned buffer will
* consist of one single bank.
+ *
+ * @return The data buffer.
*/
public DataBuffer createDataBuffer()
{
@@ -116,17 +161,40 @@ public class SinglePixelPackedSampleModel extends SampleModel
return Buffers.createBuffer(getDataType(), size);
}
-
+ /**
+ * Returns an array containing the size (in bits) for each band accessed by
+ * the <code>SampleModel</code>.
+ *
+ * @return An array.
+ *
+ * @see #getSampleSize(int)
+ */
public int[] getSampleSize()
{
- return sampleSize;
+ return (int[]) sampleSize.clone();
}
+ /**
+ * Returns the size (in bits) of the samples for the specified band.
+ *
+ * @param band the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ *
+ * @return The sample size (in bits).
+ */
public int getSampleSize(int band)
{
return sampleSize[band];
}
+ /**
+ * Returns the index in the data buffer that stores the pixel at (x, y).
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ *
+ * @return The index in the data buffer that stores the pixel at (x, y).
+ */
public int getOffset(int x, int y)
{
return scanlineStride*y + x;
@@ -142,20 +210,40 @@ public class SinglePixelPackedSampleModel extends SampleModel
return bitMasks;
}
+ /**
+ * Returns the number of data elements from a pixel in one row to the
+ * corresponding pixel in the next row.
+ *
+ * @return The scanline stride.
+ */
public int getScanlineStride()
{
return scanlineStride;
}
+ /**
+ * Creates a new <code>SinglePixelPackedSampleModel</code> that accesses
+ * the specified subset of bands.
+ *
+ * @param bands an array containing band indices (<code>null</code> not
+ * permitted).
+ *
+ * @return A new sample model.
+ *
+ * @throws NullPointerException if <code>bands</code> is <code>null</code>.
+ * @throws RasterFormatException if <code>bands.length</code> is greater
+ * than the number of bands in this model.
+ */
public SampleModel createSubsetSampleModel(int[] bands)
{
- // FIXME: Is this the right way to interpret bands?
+ if (bands.length > numBands)
+ throw new RasterFormatException("Too many bands.");
int numBands = bands.length;
int[] bitMasks = new int[numBands];
- for (int b=0; b<numBands; b++)
+ for (int b = 0; b < numBands; b++)
bitMasks[b] = this.bitMasks[bands[b]];
return new SinglePixelPackedSampleModel(dataType, width, height,
@@ -174,16 +262,20 @@ public class SinglePixelPackedSampleModel extends SampleModel
}
/**
- * This is a more efficient implementation of the default implementation in the super
- * class.
- * @param x The x-coordinate of the pixel rectangle to store in <code>obj</code>.
- * @param y The y-coordinate of the pixel rectangle to store in <code>obj</code>.
+ * This is a more efficient implementation of the default implementation in
+ * the super class.
+ * @param x The x-coordinate of the pixel rectangle to store in
+ * <code>obj</code>.
+ * @param y The y-coordinate of the pixel rectangle to store in
+ * <code>obj</code>.
* @param w The width of the pixel rectangle to store in <code>obj</code>.
* @param h The height of the pixel rectangle to store in <code>obj</code>.
- * @param obj The primitive array to store the pixels into or null to force creation.
+ * @param obj The primitive array to store the pixels into or null to force
+ * creation.
* @param data The DataBuffer that is the source of the pixel data.
* @return The primitive array containing the pixel data.
- * @see java.awt.image.SampleModel#getDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer)
+ * @see java.awt.image.SampleModel#getDataElements(int, int, int, int,
+ * java.lang.Object, java.awt.image.DataBuffer)
*/
public Object getDataElements(int x, int y, int w, int h, Object obj,
DataBuffer data)
@@ -209,10 +301,11 @@ public class SinglePixelPackedSampleModel extends SampleModel
// Seems like the only sensible thing to do.
throw new ClassCastException();
}
- if(x==0 && scanlineStride == w)
+ if(x == 0 && scanlineStride == w)
{
// The full width need to be copied therefore we can copy in one shot.
- System.arraycopy(pixelData, scanlineStride*y + data.getOffset(), obj, 0, size);
+ System.arraycopy(pixelData, scanlineStride*y + data.getOffset(), obj,
+ 0, size);
}
else
{
@@ -229,32 +322,68 @@ public class SinglePixelPackedSampleModel extends SampleModel
return obj;
}
-
+ /**
+ * Returns an array containing the samples for the pixel at (x, y) in the
+ * specified data buffer. If <code>iArray</code> is not <code>null</code>,
+ * it will be populated with the sample values and returned as the result of
+ * this function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
{
int offset = scanlineStride*y + x;
if (iArray == null) iArray = new int[numBands];
int samples = data.getElem(offset);
- for (int b=0; b<numBands; b++)
+ for (int b = 0; b < numBands; b++)
iArray[b] = (samples & bitMasks[b]) >>> bitOffsets[b];
return iArray;
}
+ /**
+ * Returns an array containing the samples for the pixels in the region
+ * specified by (x, y, w, h) in the specified data buffer. The array is
+ * ordered by pixels (that is, all the samples for the first pixel are
+ * grouped together, followed by all the samples for the second pixel, and so
+ * on). If <code>iArray</code> is not <code>null</code>, it will be
+ * populated with the sample values and returned as the result of this
+ * function (this avoids allocating a new array instance).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param iArray an array to populate with the sample values and return as
+ * the result (if <code>null</code>, a new array will be allocated).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The pixel sample values.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public int[] getPixels(int x, int y, int w, int h, int[] iArray,
DataBuffer data)
{
int offset = scanlineStride*y + x;
if (iArray == null) iArray = new int[numBands*w*h];
int outOffset = 0;
- for (y=0; y<h; y++)
+ for (y = 0; y < h; y++)
{
int lineOffset = offset;
- for (x=0; x<w; x++)
+ for (x = 0; x < w; x++)
{
int samples = data.getElem(lineOffset++);
- for (int b=0; b<numBands; b++)
+ for (int b = 0; b < numBands; b++)
iArray[outOffset++] = (samples & bitMasks[b]) >>> bitOffsets[b];
}
offset += scanlineStride;
@@ -262,6 +391,20 @@ public class SinglePixelPackedSampleModel extends SampleModel
return iArray;
}
+ /**
+ * Returns the sample value for the pixel at (x, y) in the specified data
+ * buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @return The sample value.
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public int getSample(int x, int y, int b, DataBuffer data)
{
int offset = scanlineStride*y + x;
@@ -270,16 +413,18 @@ public class SinglePixelPackedSampleModel extends SampleModel
}
/**
- * 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.
+ * This method implements a more efficient way to set data elements than the
+ * default implementation of the super class. It sets the data elements line
+ * by line instead of pixel by pixel.
+ *
* @param x The x-coordinate of the data elements in <code>obj</code>.
* @param y The y-coordinate of the data elements in <code>obj</code>.
* @param w The width of the data elements in <code>obj</code>.
* @param h The height of the data elements in <code>obj</code>.
* @param obj The primitive array containing the data elements to set.
* @param data The DataBuffer to store the data elements into.
- * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, java.lang.Object, java.awt.image.DataBuffer)
+ * @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)
@@ -373,12 +518,24 @@ public class SinglePixelPackedSampleModel extends SampleModel
}
}
+ /**
+ * Sets the samples for the pixel at (x, y) in the specified data buffer to
+ * the specified values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray the sample values (<code>null</code> not permitted).
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if either <code>iArray</code> or
+ * <code>data</code> is <code>null</code>.
+ */
public void setPixel(int x, int y, int[] iArray, DataBuffer data)
{
int offset = scanlineStride*y + x;
int samples = 0;
- for (int b=0; b<numBands; b++)
+ for (int b = 0; b < numBands; b++)
samples |= (iArray[b] << bitOffsets[b]) & bitMasks[b];
data.setElem(offset, samples);
@@ -394,7 +551,8 @@ public class SinglePixelPackedSampleModel extends SampleModel
* @param h The height of the pixel rectangle in <code>obj</code>.
* @param iArray The primitive array containing the pixels to set.
* @param data The DataBuffer to store the pixels into.
- * @see java.awt.image.SampleModel#setPixels(int, int, int, int, int[], java.awt.image.DataBuffer)
+ * @see java.awt.image.SampleModel#setPixels(int, int, int, int, int[],
+ * java.awt.image.DataBuffer)
*/
public void setPixels(int x, int y, int w, int h, int[] iArray,
DataBuffer data)
@@ -407,7 +565,7 @@ public class SinglePixelPackedSampleModel extends SampleModel
for (int xx=x; xx<(x+w); xx++)
{
int samples = 0;
- for (int b=0; b<numBands; b++)
+ for (int b = 0; b < numBands; b++)
samples |= (iArray[inOffset+b] << bitOffsets[b]) & bitMasks[b];
data.setElem(0, offset, samples);
inOffset += numBands;
@@ -416,7 +574,19 @@ public class SinglePixelPackedSampleModel extends SampleModel
}
}
-
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the
+ * specified data buffer.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ * @param data the data buffer (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>data</code> is <code>null</code>.
+ */
public void setSample(int x, int y, int b, int s, DataBuffer data)
{
int offset = scanlineStride*y + x;
@@ -428,6 +598,76 @@ public class SinglePixelPackedSampleModel extends SampleModel
}
/**
+ * Tests this sample model for equality with an arbitrary object. This
+ * method returns <code>true</code> if and only if:
+ * <ul>
+ * <li><code>obj</code> is not <code>null</code>;
+ * <li><code>obj</code> is an instance of
+ * <code>SinglePixelPackedSampleModel</code>;
+ * <li>both models have the same:
+ * <ul>
+ * <li><code>dataType</code>;
+ * <li><code>width</code>;
+ * <li><code>height</code>;
+ * <li><code>numBands</code>;
+ * <li><code>scanlineStride</code>;
+ * <li><code>bitMasks</code>;
+ * <li><code>bitOffsets</code>.
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * @param obj the object (<code>null</code> permitted)
+ *
+ * @return <code>true</code> if this model is equal to <code>obj</code>, and
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (! (obj instanceof SinglePixelPackedSampleModel))
+ return false;
+ SinglePixelPackedSampleModel that = (SinglePixelPackedSampleModel) obj;
+ if (this.dataType != that.dataType)
+ return false;
+ if (this.width != that.width)
+ return false;
+ if (this.height != that.height)
+ return false;
+ if (this.numBands != that.numBands)
+ return false;
+ if (this.scanlineStride != that.scanlineStride)
+ return false;
+ if (!Arrays.equals(this.bitMasks, that.bitMasks))
+ return false;
+ if (!Arrays.equals(this.bitOffsets, that.bitOffsets))
+ return false;
+ return true;
+ }
+
+ /**
+ * Returns a hash code for this <code>SinglePixelPackedSampleModel</code>.
+ *
+ * @return A hash code.
+ */
+ public int hashCode()
+ {
+ // this hash code won't match Sun's, but that shouldn't matter...
+ int result = 193;
+ result = 37 * result + dataType;
+ result = 37 * result + width;
+ result = 37 * result + height;
+ result = 37 * result + numBands;
+ result = 37 * result + scanlineStride;
+ for (int i = 0; i < bitMasks.length; i++)
+ result = 37 * result + bitMasks[i];
+ for (int i = 0; i < bitOffsets.length; i++)
+ result = 37 * result + bitOffsets[i];
+ return result;
+ }
+
+ /**
* Creates a String with some information about this SampleModel.
* @return A String describing this SampleModel.
* @see java.lang.Object#toString()
@@ -438,9 +678,10 @@ public class SinglePixelPackedSampleModel extends SampleModel
result.append(getClass().getName());
result.append("[");
result.append("scanlineStride=").append(scanlineStride);
- for(int i=0; i < bitMasks.length; i+=1)
+ for(int i = 0; i < bitMasks.length; i+=1)
{
- result.append(", mask[").append(i).append("]=0x").append(Integer.toHexString(bitMasks[i]));
+ result.append(", mask[").append(i).append("]=0x").append(
+ Integer.toHexString(bitMasks[i]));
}
result.append("]");
diff --git a/java/awt/image/WritableRaster.java b/java/awt/image/WritableRaster.java
index 2e5462fd9..473c6fe41 100644
--- a/java/awt/image/WritableRaster.java
+++ b/java/awt/image/WritableRaster.java
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000, 2002, 2003 Free Software Foundation
+/* Copyright (C) 2000, 2002, 2003, 2006, Free Software Foundation
This file is part of GNU Classpath.
@@ -41,61 +41,98 @@ import java.awt.Point;
import java.awt.Rectangle;
/**
+ * A raster with methods to support updating pixel values.
+ *
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
*/
public class WritableRaster extends Raster
{
+ /**
+ * Creates a new <code>WritableRaster</code>.
+ *
+ * @param sampleModel the sample model.
+ * @param origin the origin.
+ */
protected WritableRaster(SampleModel sampleModel, Point origin)
{
this(sampleModel, sampleModel.createDataBuffer(), origin);
}
- protected WritableRaster(SampleModel sampleModel,
- DataBuffer dataBuffer, Point origin)
+ /**
+ * Creates a new <code>WritableRaster</code> instance.
+ *
+ * @param sampleModel the sample model.
+ * @param dataBuffer the data buffer.
+ * @param origin the origin.
+ */
+ protected WritableRaster(SampleModel sampleModel, DataBuffer dataBuffer,
+ Point origin)
{
this(sampleModel, dataBuffer,
- new Rectangle(origin != null ? origin.x : 0,
+ new Rectangle(origin != null ? origin.x : 0,
origin != null ? origin.y : 0,
- sampleModel.getWidth(), sampleModel.getHeight()),
- origin,
- null);
+ sampleModel.getWidth(), sampleModel.getHeight()),
+ origin, null);
}
+ /**
+ * Creates a new <code>WritableRaster</code> instance.
+ *
+ * @param sampleModel the sample model.
+ * @param dataBuffer the data buffer.
+ * @param aRegion the raster's bounds.
+ * @param sampleModelTranslate the translation.
+ * @param parent the parent.
+ */
protected WritableRaster(SampleModel sampleModel,
- DataBuffer dataBuffer,
- Rectangle aRegion,
- Point sampleModelTranslate,
- WritableRaster parent)
+ DataBuffer dataBuffer,
+ Rectangle aRegion,
+ Point sampleModelTranslate,
+ WritableRaster parent)
{
- super(sampleModel, dataBuffer, aRegion, sampleModelTranslate,
- parent);
+ super(sampleModel, dataBuffer, aRegion, sampleModelTranslate, parent);
}
+ /**
+ * Returns the raster's parent, cast as a {@link WritableRaster}.
+ *
+ * @return The raster's parent.
+ */
public WritableRaster getWritableParent()
{
return (WritableRaster) getParent();
}
+ /**
+ * @param childMinX
+ * @param childMinY
+ * @return
+ */
public WritableRaster createWritableTranslatedChild(int childMinX,
- int childMinY)
+ int childMinY)
{
// This mirrors the code from the super class
int tcx = sampleModelTranslateX - minX + childMinX;
int tcy = sampleModelTranslateY - minY + childMinY;
return new WritableRaster(sampleModel, dataBuffer,
- new Rectangle(childMinX, childMinY,
- width, height),
- new Point(tcx, tcy),
- this);
+ new Rectangle(childMinX, childMinY, width, height),
+ new Point(tcx, tcy), this);
}
- public WritableRaster createWritableChild(int parentX,
- int parentY,
- int w, int h,
- int childMinX,
- int childMinY,
- int[] bandList)
+ /**
+ *
+ * @param parentX
+ * @param parentY
+ * @param w
+ * @param h
+ * @param childMinX
+ * @param childMinY
+ * @param bandList
+ * @return
+ */
+ public WritableRaster createWritableChild(int parentX, int parentY,
+ int w, int h, int childMinX, int childMinY, int[] bandList)
{
// This mirrors the code from the super class
@@ -106,51 +143,52 @@ public class WritableRaster extends Raster
sampleModel :
sampleModel.createSubsetSampleModel(bandList);
- return new
- WritableRaster(sm, dataBuffer,
- new Rectangle(childMinX, childMinY,
- w, h),
- new Point(sampleModelTranslateX+childMinX-parentX,
- sampleModelTranslateY+childMinY-parentY),
- this);
+ return new WritableRaster(sm, dataBuffer,
+ new Rectangle(childMinX, childMinY, w, h),
+ new Point(sampleModelTranslateX + childMinX - parentX,
+ sampleModelTranslateY + childMinY - parentY),
+ this);
}
public void setDataElements(int x, int y, Object inData)
{
- sampleModel.setDataElements(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- inData, dataBuffer);
+ sampleModel.setDataElements(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, inData, dataBuffer);
}
public void setDataElements(int x, int y, Raster inRaster)
{
- Object dataElements = getDataElements(0, 0,
- inRaster.getWidth(),
- inRaster.getHeight(),
- null);
+ Object dataElements = getDataElements(0, 0, inRaster.getWidth(),
+ inRaster.getHeight(), null);
setDataElements(x, y, dataElements);
}
- public void setDataElements(int x, int y, int w, int h,
- Object inData)
+ public void setDataElements(int x, int y, int w, int h, Object inData)
{
- sampleModel.setDataElements(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- w, h, inData, dataBuffer);
+ sampleModel.setDataElements(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h, inData, dataBuffer);
}
+ /**
+ *
+ * @param srcRaster
+ */
public void setRect(Raster srcRaster)
{
setRect(0, 0, srcRaster);
}
+ /**
+ *
+ * @param dx
+ * @param dy
+ * @param srcRaster
+ */
public void setRect(int dx, int dy, Raster srcRaster)
{
- Rectangle targetUnclipped = new Rectangle(srcRaster.getMinX()+dx,
- srcRaster.getMinY()+dy,
- srcRaster.getWidth(),
- srcRaster.getHeight());
-
+ Rectangle targetUnclipped = new Rectangle(srcRaster.getMinX() + dx,
+ srcRaster.getMinY() + dy, srcRaster.getWidth(), srcRaster.getHeight());
+
Rectangle target = getBounds().intersection(targetUnclipped);
if (target.isEmpty()) return;
@@ -169,97 +207,225 @@ public class WritableRaster extends Raster
But this is probably not the place to consider such
optimizations.*/
- int[] pixels = srcRaster.getPixels(sx, sy,
- target.width, target.height,
- (int[]) null);
+ int[] pixels = srcRaster.getPixels(sx, sy, target.width, target.height,
+ (int[]) null);
setPixels(target.x, target.y, target.width, target.height, pixels);
}
+ /**
+ * Sets the samples for the pixel at (x, y) in the raster to the specified
+ * values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param iArray the sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>iArray</code> is <code>null</code>.
+ */
public void setPixel(int x, int y, int[] iArray)
{
- sampleModel.setPixel(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- iArray, dataBuffer);
+ sampleModel.setPixel(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ iArray, dataBuffer);
}
+ /**
+ * Sets the samples for the pixel at (x, y) in the raster to the specified
+ * values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param fArray the sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>fArray</code> is <code>null</code>.
+ */
public void setPixel(int x, int y, float[] fArray)
{
- sampleModel.setPixel(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- fArray, dataBuffer);
+ sampleModel.setPixel(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ fArray, dataBuffer);
}
+ /**
+ * Sets the samples for the pixel at (x, y) in the raster to the specified
+ * values.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param dArray the sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>dArray</code> is <code>null</code>.
+ */
public void setPixel(int x, int y, double[] dArray)
{
- sampleModel.setPixel(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- dArray, dataBuffer);
+ sampleModel.setPixel(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ dArray, dataBuffer);
}
+ /**
+ * Sets the sample values for the pixels in the region specified by
+ * (x, y, w, h) in the raster. The array is ordered by pixels (that is, all
+ * the samples for the first pixel are grouped together, followed by all the
+ * samples for the second pixel, and so on).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param iArray the pixel sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>iArray</code> is <code>null</code>.
+ */
public void setPixels(int x, int y, int w, int h, int[] iArray)
{
- sampleModel.setPixels(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- w, h, iArray, dataBuffer);
+ sampleModel.setPixels(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ w, h, iArray, dataBuffer);
}
+ /**
+ * Sets the sample values for the pixels in the region specified by
+ * (x, y, w, h) in the raster. The array is ordered by pixels (that is, all
+ * the samples for the first pixel are grouped together, followed by all the
+ * samples for the second pixel, and so on).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param fArray the pixel sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>fArray</code> is <code>null</code>.
+ */
public void setPixels(int x, int y, int w, int h, float[] fArray)
{
- sampleModel.setPixels(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- w, h, fArray, dataBuffer);
+ sampleModel.setPixels(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ w, h, fArray, dataBuffer);
}
+ /**
+ * Sets the sample values for the pixels in the region specified by
+ * (x, y, w, h) in the raster. The array is ordered by pixels (that is, all
+ * the samples for the first pixel are grouped together, followed by all the
+ * samples for the second pixel, and so on).
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param dArray the pixel sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>dArray</code> is <code>null</code>.
+ */
public void setPixels(int x, int y, int w, int h, double[] dArray)
{
- sampleModel.setPixels(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- w, h, dArray, dataBuffer);
+ sampleModel.setPixels(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ w, h, dArray, dataBuffer);
}
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the raster.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ */
public void setSample(int x, int y, int b, int s)
{
- sampleModel.setSample(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- b, s, dataBuffer);
+ sampleModel.setSample(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ b, s, dataBuffer);
}
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the raster.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ */
public void setSample(int x, int y, int b, float s)
{
- sampleModel.setSample(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- b, s, dataBuffer);
+ sampleModel.setSample(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ b, s, dataBuffer);
}
+ /**
+ * Sets the sample value for a band for the pixel at (x, y) in the raster.
+ *
+ * @param x the x-coordinate of the pixel.
+ * @param y the y-coordinate of the pixel.
+ * @param b the band (in the range <code>0</code> to
+ * <code>getNumBands() - 1</code>).
+ * @param s the sample value.
+ */
public void setSample(int x, int y, int b, double s)
{
- sampleModel.setSample(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- b, s, dataBuffer);
+ sampleModel.setSample(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ b, s, dataBuffer);
}
+ /**
+ * Sets the sample values for one band for the pixels in the region
+ * specified by (x, y, w, h) in the raster.
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param iArray the sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>iArray</code> is <code>null</code>.
+ */
public void setSamples(int x, int y, int w, int h, int b,
- int[] iArray)
+ int[] iArray)
{
- sampleModel.setSamples(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- w, h, b, iArray, dataBuffer);
+ sampleModel.setSamples(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ w, h, b, iArray, dataBuffer);
}
+ /**
+ * Sets the sample values for one band for the pixels in the region
+ * specified by (x, y, w, h) in the raster.
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param fArray the sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>fArray</code> is <code>null</code>.
+ */
public void setSamples(int x, int y, int w, int h, int b,
- float[] fArray)
+ float[] fArray)
{
- sampleModel.setSamples(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- w, h, b, fArray, dataBuffer);
+ sampleModel.setSamples(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ w, h, b, fArray, dataBuffer);
}
+ /**
+ * Sets the sample values for one band for the pixels in the region
+ * specified by (x, y, w, h) in the raster.
+ *
+ * @param x the x-coordinate of the top-left pixel.
+ * @param y the y-coordinate of the top-left pixel.
+ * @param w the width of the region of pixels.
+ * @param h the height of the region of pixels.
+ * @param b the band (in the range <code>0</code> to
+ * </code>getNumBands() - 1</code>).
+ * @param dArray the sample values (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>dArray</code> is <code>null</code>.
+ */
public void setSamples(int x, int y, int w, int h, int b,
- double[] dArray)
+ double[] dArray)
{
- sampleModel.setSamples(x-sampleModelTranslateX,
- y-sampleModelTranslateY,
- w, h, b, dArray, dataBuffer);
+ sampleModel.setSamples(x - sampleModelTranslateX, y - sampleModelTranslateY,
+ w, h, b, dArray, dataBuffer);
}
}
diff --git a/java/awt/peer/ComponentPeer.java b/java/awt/peer/ComponentPeer.java
index 97b96f49c..bc6e3a457 100644
--- a/java/awt/peer/ComponentPeer.java
+++ b/java/awt/peer/ComponentPeer.java
@@ -153,6 +153,12 @@ public interface ComponentPeer
* {@link Component#getMinimumSize()}.
*
* @return the minimum size for the component
+ *
+ * @specnote Presumably this method got added to replace minimumSize().
+ * However, testing shows that this is never called in the RI
+ * (tested with JDK5), but instead minimumSize() is called
+ * directly. It is advisable to implement this method to delegate
+ * to minimumSize() and put the real implementation in there.
*/
Dimension getMinimumSize();
@@ -161,6 +167,12 @@ public interface ComponentPeer
* {@link Component#getPreferredSize()}.
*
* @return the preferred size for the component
+ *
+ * @specnote Presumably this method got added to replace preferredSize().
+ * However, testing shows that this is never called in the RI
+ * (tested with JDK5), but instead preferredSize() is called
+ * directly. It is advisable to implement this method to delegate
+ * to preferredSize() and put the real implementation in there.
*/
Dimension getPreferredSize();
@@ -262,12 +274,21 @@ public interface ComponentPeer
* Requests that this component receives the focus. This is called from
* {@link Component#requestFocus()}.
*
- * @param source TODO
- * @param bool1 TODO
- * @param bool2 TODO
- * @param x TODO
- */
- boolean requestFocus(Component source, boolean bool1, boolean bool2, long x);
+ * This method is only called for heavyweight component's peers. Lightweight
+ * components ask their nearest heavyweight component to request focus.
+ * It's up to the heavyweight peer to decide if any of it's lightweight
+ * descendants are allowed to receive keyboard input focus or not. If the
+ * focus request is finally approved, then the peer must post a FOCUS_GAINED
+ * event for the requested component.
+ *
+ * @param request the component for which the focus is requested
+ * @param temporary indicates if the focus change is temporary (true) or
+ * permanent (false)
+ * @param allowWindowFocus indicates if it's allowed to change window focus
+ * @param time the timestamp
+ */
+ boolean requestFocus(Component request, boolean temporary,
+ boolean allowWindowFocus, long time);
/**
* Notifies the peer that the bounds of this component have changed. This
diff --git a/java/awt/peer/MouseInfoPeer.java b/java/awt/peer/MouseInfoPeer.java
new file mode 100644
index 000000000..e9923a653
--- /dev/null
+++ b/java/awt/peer/MouseInfoPeer.java
@@ -0,0 +1,61 @@
+/* MouseInfoPeer.java -- peer interface for MouseInfo
+ 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.awt.peer;
+
+import java.awt.Point;
+import java.awt.Window;
+
+/**
+ * MouseInfoPeer is the peer interface java.awt.MouseInfo.
+ *
+ * @author Sven de Marothy
+ * @since 1.5
+ */
+public interface MouseInfoPeer
+{
+ /**
+ * Get the mouse pointer coordinates and store them in p (obviously non-null)
+ * returns the index of the current screen device of the mouse.
+ */
+ public int fillPointWithCoords(Point p);
+
+ /**
+ * Returns whether a given Window is under the mouse.
+ */
+ public boolean isWindowUnderMouse(Window w);
+}
diff --git a/java/awt/peer/WindowPeer.java b/java/awt/peer/WindowPeer.java
index 6c014de0b..00d103579 100644
--- a/java/awt/peer/WindowPeer.java
+++ b/java/awt/peer/WindowPeer.java
@@ -1,5 +1,5 @@
/* WindowPeer.java -- Interface for window peers
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -44,7 +44,8 @@ public interface WindowPeer extends ContainerPeer
void toFront();
/**
- * FIXME: unknown.
+ * Update the always-on-top status of the Window.
+ *
* @since 1.5
*/
void updateAlwaysOnTop();
diff --git a/java/io/ObjectInputStream.java b/java/io/ObjectInputStream.java
index a37ad73fd..6f1eb82b1 100644
--- a/java/io/ObjectInputStream.java
+++ b/java/io/ObjectInputStream.java
@@ -539,8 +539,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 +558,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);
diff --git a/java/io/ObjectStreamField.java b/java/io/ObjectStreamField.java
index 61ccdc7db..fbb1381dc 100644
--- a/java/io/ObjectStreamField.java
+++ b/java/io/ObjectStreamField.java
@@ -111,28 +111,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 +123,7 @@ public class ObjectStreamField implements Comparable
{
}
}
-
+
/**
* This method returns the name of the field represented by the
* ObjectStreamField instance.
diff --git a/java/io/PrintStream.java b/java/io/PrintStream.java
index 99af25583..98461db2b 100644
--- a/java/io/PrintStream.java
+++ b/java/io/PrintStream.java
@@ -87,8 +87,76 @@ public class PrintStream extends FilterOutputStream
private boolean auto_flush;
/**
- * This method intializes a new <code>PrintStream</code> object to write
- * to the specified output sink.
+ * This method initializes a new <code>PrintStream</code> object to write
+ * to the specified output File. Doesn't autoflush.
+ *
+ * @param file The <code>File</code> to write to.
+ * @throws FileNotFoundException if an error occurs while opening the file.
+ *
+ * @since 1.5
+ */
+ public PrintStream (File file)
+ throws FileNotFoundException
+ {
+ this (new FileOutputStream(file), false);
+ }
+
+ /**
+ * This method initializes a new <code>PrintStream</code> object to write
+ * to the specified output File. Doesn't autoflush.
+ *
+ * @param file The <code>File</code> to write to.
+ * @param encoding The name of the character encoding to use for this
+ * object.
+ * @throws FileNotFoundException If an error occurs while opening the file.
+ * @throws UnsupportedEncodingException If the charset specified by
+ * <code>encoding</code> is invalid.
+ *
+ * @since 1.5
+ */
+ public PrintStream (File file, String encoding)
+ throws FileNotFoundException,UnsupportedEncodingException
+ {
+ this (new FileOutputStream(file), false, encoding);
+ }
+
+ /**
+ * This method initializes a new <code>PrintStream</code> object to write
+ * to the specified output File. Doesn't autoflush.
+ *
+ * @param fileName The name of the <code>File</code> to write to.
+ * @throws FileNotFoundException if an error occurs while opening the file,
+ *
+ * @since 1.5
+ */
+ public PrintStream (String fileName)
+ throws FileNotFoundException
+ {
+ this (new FileOutputStream(new File(fileName)), false);
+ }
+
+ /**
+ * This method initializes a new <code>PrintStream</code> object to write
+ * to the specified output File. Doesn't autoflush.
+ *
+ * @param fileName The name of the <code>File</code> to write to.
+ * @param encoding The name of the character encoding to use for this
+ * object.
+ * @throws FileNotFoundException if an error occurs while opening the file.
+ * @throws UnsupportedEncodingException If the charset specified by
+ * <code>encoding</code> is invalid.
+ *
+ * @since 1.5
+ */
+ public PrintStream (String fileName, String encoding)
+ throws FileNotFoundException,UnsupportedEncodingException
+ {
+ this (new FileOutputStream(new File(fileName)), false, encoding);
+ }
+
+ /**
+ * This method initializes a new <code>PrintStream</code> object to write
+ * to the specified output sink. Doesn't autoflush.
*
* @param out The <code>OutputStream</code> to write to.
*/
@@ -98,7 +166,7 @@ public class PrintStream extends FilterOutputStream
}
/**
- * This method intializes a new <code>PrintStream</code> object to write
+ * This method initializes a new <code>PrintStream</code> object to write
* to the specified output sink. This constructor also allows "auto-flush"
* functionality to be specified where the stream will be flushed after
* every <code>print</code> or <code>println</code> call, when the
@@ -127,7 +195,7 @@ public class PrintStream extends FilterOutputStream
}
/**
- * This method intializes a new <code>PrintStream</code> object to write
+ * This method initializes a new <code>PrintStream</code> object to write
* to the specified output sink. This constructor also allows "auto-flush"
* functionality to be specified where the stream will be flushed after
* every <code>print</code> or <code>println</code> call, when the
diff --git a/java/lang/Iterable.java b/java/lang/Iterable.java
index 8223bcf8c..35c426484 100644
--- a/java/lang/Iterable.java
+++ b/java/lang/Iterable.java
@@ -38,7 +38,8 @@ exception statement from your version. */
package java.lang;
-import java.util.Iterator;
+// We only need Iterator, but we import * to support lib/mkcollections.pl
+import java.util.*;
/**
* This interface is used to indicate that a given class can be
diff --git a/java/lang/StrictMath.java b/java/lang/StrictMath.java
index 548a6f1c1..ec74ca413 100644
--- a/java/lang/StrictMath.java
+++ b/java/lang/StrictMath.java
@@ -1,5 +1,5 @@
/* java.lang.StrictMath -- common mathematical functions, strict Java
- Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -633,6 +633,381 @@ public final strictfp class StrictMath
}
/**
+ * Returns the hyperbolic sine of <code>x</code> which is defined as
+ * (exp(x) - exp(-x)) / 2.
+ *
+ * Special cases:
+ * <ul>
+ * <li>If the argument is NaN, the result is NaN</li>
+ * <li>If the argument is positive infinity, the result is positive
+ * infinity.</li>
+ * <li>If the argument is negative infinity, the result is negative
+ * infinity.</li>
+ * <li>If the argument is zero, the result is zero.</li>
+ * </ul>
+ *
+ * @param x the argument to <em>sinh</em>
+ * @return the hyperbolic sine of <code>x</code>
+ *
+ * @since 1.5
+ */
+ public static double sinh(double x)
+ {
+ // Method :
+ // mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
+ // 1. Replace x by |x| (sinh(-x) = -sinh(x)).
+ // 2.
+ // E + E/(E+1)
+ // 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x)
+ // 2
+ //
+ // 22 <= x <= lnovft : sinh(x) := exp(x)/2
+ // lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2)
+ // ln2ovft < x : sinh(x) := +inf (overflow)
+
+ double t, w, h;
+
+ long bits;
+ long h_bits;
+ long l_bits;
+
+ // handle special cases
+ if (x != x)
+ return x;
+ if (x == Double.POSITIVE_INFINITY)
+ return Double.POSITIVE_INFINITY;
+ if (x == Double.NEGATIVE_INFINITY)
+ return Double.NEGATIVE_INFINITY;
+
+ if (x < 0)
+ h = - 0.5;
+ else
+ h = 0.5;
+
+ bits = Double.doubleToLongBits(x);
+ h_bits = getHighDWord(bits) & 0x7fffffffL; // ignore sign
+ l_bits = getLowDWord(bits);
+
+ // |x| in [0, 22], return sign(x) * 0.5 * (E+E/(E+1))
+ if (h_bits < 0x40360000L) // |x| < 22
+ {
+ if (h_bits < 0x3e300000L) // |x| < 2^-28
+ return x; // for tiny arguments return x
+
+ t = expm1(abs(x));
+
+ if (h_bits < 0x3ff00000L)
+ return h * (2.0 * t - t * t / (t + 1.0));
+
+ return h * (t + t / (t + 1.0));
+ }
+
+ // |x| in [22, log(Double.MAX_VALUE)], return 0.5 * exp(|x|)
+ if (h_bits < 0x40862e42L)
+ return h * exp(abs(x));
+
+ // |x| in [log(Double.MAX_VALUE), overflowthreshold]
+ if ((h_bits < 0x408633ceL)
+ || ((h_bits == 0x408633ceL) && (l_bits <= 0x8fb9f87dL)))
+ {
+ w = exp(0.5 * abs(x));
+ t = h * w;
+
+ return t * w;
+ }
+
+ // |x| > overflowthershold
+ return h * Double.POSITIVE_INFINITY;
+ }
+
+ /**
+ * Returns the hyperbolic cosine of <code>x</code>, which is defined as
+ * (exp(x) + exp(-x)) / 2.
+ *
+ * Special cases:
+ * <ul>
+ * <li>If the argument is NaN, the result is NaN</li>
+ * <li>If the argument is positive infinity, the result is positive
+ * infinity.</li>
+ * <li>If the argument is negative infinity, the result is positive
+ * infinity.</li>
+ * <li>If the argument is zero, the result is one.</li>
+ * </ul>
+ *
+ * @param x the argument to <em>cosh</em>
+ * @return the hyperbolic cosine of <code>x</code>
+ *
+ * @since 1.5
+ */
+ public static double cosh(double x)
+ {
+ // Method :
+ // mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2
+ // 1. Replace x by |x| (cosh(x) = cosh(-x)).
+ // 2.
+ // [ exp(x) - 1 ]^2
+ // 0 <= x <= ln2/2 : cosh(x) := 1 + -------------------
+ // 2*exp(x)
+ //
+ // exp(x) + 1/exp(x)
+ // ln2/2 <= x <= 22 : cosh(x) := ------------------
+ // 2
+ // 22 <= x <= lnovft : cosh(x) := exp(x)/2
+ // lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2)
+ // ln2ovft < x : cosh(x) := +inf (overflow)
+
+ double t, w;
+ long bits;
+ long hx;
+ long lx;
+
+ // handle special cases
+ if (x != x)
+ 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) & 0x7fffffffL; // ignore sign
+ lx = getLowDWord(bits);
+
+ // |x| in [0, 0.5 * ln(2)], return 1 + expm1(|x|)^2 / (2 * exp(|x|))
+ if (hx < 0x3fd62e43L)
+ {
+ t = expm1(abs(x));
+ w = 1.0 + t;
+
+ // for tiny arguments return 1.
+ 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 < 0x40360000L)
+ {
+ t = exp(abs(x));
+
+ return 0.5 * t + 0.5 / t;
+ }
+
+ // |x| in [22, log(Double.MAX_VALUE)], return 0.5 * exp(|x|)
+ if (hx < 0x40862e42L)
+ return 0.5 * exp(abs(x));
+
+ // |x| in [log(Double.MAX_VALUE), overflowthreshold],
+ // return exp(x/2)/2 * exp(x/2)
+ if ((hx < 0x408633ceL)
+ || ((hx == 0x408633ceL) && (lx <= 0x8fb9f87dL)))
+ {
+ w = exp(0.5 * abs(x));
+ t = 0.5 * w;
+
+ return t * w;
+ }
+
+ // |x| > overflowthreshold
+ return Double.POSITIVE_INFINITY;
+ }
+
+ /**
+ * Returns the hyperbolic tangent of <code>x</code>, which is defined as
+ * (exp(x) - exp(-x)) / (exp(x) + exp(-x)), i.e. sinh(x) / cosh(x).
+ *
+ Special cases:
+ * <ul>
+ * <li>If the argument is NaN, the result is NaN</li>
+ * <li>If the argument is positive infinity, the result is 1.</li>
+ * <li>If the argument is negative infinity, the result is -1.</li>
+ * <li>If the argument is zero, the result is zero.</li>
+ * </ul>
+ *
+ * @param x the argument to <em>tanh</em>
+ * @return the hyperbolic tagent of <code>x</code>
+ *
+ * @since 1.5
+ */
+ public static double tanh(double x)
+ {
+ // Method :
+ // 0. tanh(x) is defined to be (exp(x) - exp(-x)) / (exp(x) + exp(-x))
+ // 1. reduce x to non-negative by tanh(-x) = -tanh(x).
+ // 2. 0 <= x <= 2^-55 : tanh(x) := x * (1.0 + x)
+ // -t
+ // 2^-55 < x <= 1 : tanh(x) := -----; t = expm1(-2x)
+ // t + 2
+ // 2
+ // 1 <= x <= 22.0 : tanh(x) := 1 - ----- ; t=expm1(2x)
+ // t + 2
+ // 22.0 < x <= INF : tanh(x) := 1.
+
+ double t, z;
+
+ long bits;
+ long h_bits;
+
+ // handle special cases
+ if (x != x)
+ return x;
+ if (x == Double.POSITIVE_INFINITY)
+ return 1.0;
+ if (x == Double.NEGATIVE_INFINITY)
+ return -1.0;
+
+ bits = Double.doubleToLongBits(x);
+ h_bits = getHighDWord(bits) & 0x7fffffffL; // ingnore sign
+
+ if (h_bits < 0x40360000L) // |x| < 22
+ {
+ if (h_bits < 0x3c800000L) // |x| < 2^-55
+ return x * (1.0 + x);
+
+ if (h_bits >= 0x3ff00000L) // |x| >= 1
+ {
+ t = expm1(2.0 * abs(x));
+ z = 1.0 - 2.0 / (t + 2.0);
+ }
+ else // |x| < 1
+ {
+ t = expm1(-2.0 * abs(x));
+ z = -t / (t + 2.0);
+ }
+ }
+ else // |x| >= 22
+ z = 1.0;
+
+ return (x >= 0) ? z : -z;
+ }
+
+ /**
+ * Returns the lower two words of a long. This is intended to be
+ * used like this:
+ * <code>getLowDWord(Double.doubleToLongBits(x))</code>.
+ */
+ private static long getLowDWord(long x)
+ {
+ return x & 0x00000000ffffffffL;
+ }
+
+ /**
+ * Returns the higher two words of a long. This is intended to be
+ * used like this:
+ * <code>getHighDWord(Double.doubleToLongBits(x))</code>.
+ */
+ private static long getHighDWord(long x)
+ {
+ return (x & 0xffffffff00000000L) >> 32;
+ }
+
+ /**
+ * Returns a double with the IEEE754 bit pattern given in the lower
+ * and higher two words <code>lowDWord</code> and <code>highDWord</code>.
+ */
+ private static double buildDouble(long lowDWord, long highDWord)
+ {
+ return Double.longBitsToDouble(((highDWord & 0xffffffffL) << 32)
+ | (lowDWord & 0xffffffffL));
+ }
+
+ /**
+ * Returns the cube root of <code>x</code>. The sign of the cube root
+ * is equal to the sign of <code>x</code>.
+ *
+ * Special cases:
+ * <ul>
+ * <li>If the argument is NaN, the result is NaN</li>
+ * <li>If the argument is positive infinity, the result is positive
+ * infinity.</li>
+ * <li>If the argument is negative infinity, the result is negative
+ * infinity.</li>
+ * <li>If the argument is zero, the result is zero with the same
+ * sign as the argument.</li>
+ * </ul>
+ *
+ * @param x the number to take the cube root of
+ * @return the cube root of <code>x</code>
+ * @see #sqrt(double)
+ *
+ * @since 1.5
+ */
+ public static double cbrt(double x)
+ {
+ boolean negative = (x < 0);
+ double r;
+ double s;
+ double t;
+ double w;
+
+ long bits;
+ long l;
+ long h;
+
+ // handle the 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)
+ return x;
+
+ x = abs(x);
+ bits = Double.doubleToLongBits(x);
+
+ if (bits < 0x0010000000000000L) // subnormal number
+ {
+ t = TWO_54;
+ t *= x;
+
+ // __HI(t)=__HI(t)/3+B2;
+ bits = Double.doubleToLongBits(t);
+ h = getHighDWord(bits);
+ l = getLowDWord(bits);
+
+ h = h / 3 + CBRT_B2;
+
+ t = buildDouble(l, h);
+ }
+ else
+ {
+ // __HI(t)=__HI(x)/3+B1;
+ h = getHighDWord(bits);
+ l = 0;
+
+ h = h / 3 + CBRT_B1;
+ t = buildDouble(l, h);
+ }
+
+ // new cbrt to 23 bits
+ r = t * t / x;
+ s = CBRT_C + r * t;
+ t *= CBRT_G + CBRT_F / (s + CBRT_E + CBRT_D / s);
+
+ // chopped to 20 bits and make it larger than cbrt(x)
+ bits = Double.doubleToLongBits(t);
+ h = getHighDWord(bits);
+
+ // __LO(t)=0;
+ // __HI(t)+=0x00000001;
+ l = 0;
+ h += 1;
+ t = buildDouble(l, h);
+
+ // one step newton iteration to 53 bits with error less than 0.667 ulps
+ s = t * t; // t * t is exact
+ r = x / s;
+ w = t + t;
+ r = (r - t) / (w + r); // r - t is exact
+ t = t + t * r;
+
+ return negative ? -t : t;
+ }
+
+ /**
* Take <em>e</em><sup>a</sup>. The opposite of <code>log()</code>. If the
* argument is NaN, the result is NaN; if the argument is positive infinity,
* the result is positive infinity; and if the argument is negative
@@ -694,6 +1069,254 @@ public final strictfp class StrictMath
}
/**
+ * Returns <em>e</em><sup>x</sup> - 1.
+ * Special cases:
+ * <ul>
+ * <li>If the argument is NaN, the result is NaN.</li>
+ * <li>If the argument is positive infinity, the result is positive
+ * infinity</li>
+ * <li>If the argument is negative infinity, the result is -1.</li>
+ * <li>If the argument is zero, the result is zero.</li>
+ * </ul>
+ *
+ * @param x the argument to <em>e</em><sup>x</sup> - 1.
+ * @return <em>e</em> raised to the power <code>x</code> minus one.
+ * @see #exp(double)
+ */
+ public static double expm1(double x)
+ {
+ // Method
+ // 1. Argument reduction:
+ // Given x, find r and integer k such that
+ //
+ // x = k * ln(2) + r, |r| <= 0.5 * ln(2)
+ //
+ // Here a correction term c will be computed to compensate
+ // the error in r when rounded to a floating-point number.
+ //
+ // 2. Approximating expm1(r) by a special rational function on
+ // the interval [0, 0.5 * ln(2)]:
+ // Since
+ // r*(exp(r)+1)/(exp(r)-1) = 2 + r^2/6 - r^4/360 + ...
+ // we define R1(r*r) by
+ // r*(exp(r)+1)/(exp(r)-1) = 2 + r^2/6 * R1(r*r)
+ // That is,
+ // R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r)
+ // = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r))
+ // = 1 - r^2/60 + r^4/2520 - r^6/100800 + ...
+ // We use a special Remes algorithm on [0, 0.347] to generate
+ // a polynomial of degree 5 in r*r to approximate R1. The
+ // maximum error of this polynomial approximation is bounded
+ // by 2**-61. In other words,
+ // R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5
+ // where Q1 = -1.6666666666666567384E-2,
+ // Q2 = 3.9682539681370365873E-4,
+ // Q3 = -9.9206344733435987357E-6,
+ // Q4 = 2.5051361420808517002E-7,
+ // Q5 = -6.2843505682382617102E-9;
+ // (where z=r*r, and Q1 to Q5 are called EXPM1_Qx in the source)
+ // with error bounded by
+ // | 5 | -61
+ // | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2
+ // | |
+ //
+ // expm1(r) = exp(r)-1 is then computed by the following
+ // specific way which minimize the accumulation rounding error:
+ // 2 3
+ // r r [ 3 - (R1 + R1*r/2) ]
+ // expm1(r) = r + --- + --- * [--------------------]
+ // 2 2 [ 6 - r*(3 - R1*r/2) ]
+ //
+ // To compensate the error in the argument reduction, we use
+ // expm1(r+c) = expm1(r) + c + expm1(r)*c
+ // ~ expm1(r) + c + r*c
+ // Thus c+r*c will be added in as the correction terms for
+ // expm1(r+c). Now rearrange the term to avoid optimization
+ // screw up:
+ // ( 2 2 )
+ // ({ ( r [ R1 - (3 - R1*r/2) ] ) } r )
+ // expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- )
+ // ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 )
+ // ( )
+ //
+ // = r - E
+ // 3. Scale back to obtain expm1(x):
+ // From step 1, we have
+ // expm1(x) = either 2^k*[expm1(r)+1] - 1
+ // = or 2^k*[expm1(r) + (1-2^-k)]
+ // 4. Implementation notes:
+ // (A). To save one multiplication, we scale the coefficient Qi
+ // to Qi*2^i, and replace z by (x^2)/2.
+ // (B). To achieve maximum accuracy, we compute expm1(x) by
+ // (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf)
+ // (ii) if k=0, return r-E
+ // (iii) if k=-1, return 0.5*(r-E)-0.5
+ // (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E)
+ // else return 1.0+2.0*(r-E);
+ // (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1)
+ // (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else
+ // (vii) return 2^k(1-((E+2^-k)-r))
+
+ boolean negative = (x < 0);
+ double y, hi, lo, c, t, e, hxs, hfx, r1;
+ int k;
+
+ long bits;
+ long h_bits;
+ long l_bits;
+
+ c = 0.0;
+ y = abs(x);
+
+ bits = Double.doubleToLongBits(y);
+ h_bits = getHighDWord(bits);
+ l_bits = getLowDWord(bits);
+
+ // handle special cases and large arguments
+ if (h_bits >= 0x4043687aL) // if |x| >= 56 * ln(2)
+ {
+ if (h_bits >= 0x40862e42L) // if |x| >= EXP_LIMIT_H
+ {
+ if (h_bits >= 0x7ff00000L)
+ {
+ if (((h_bits & 0x000fffffL) | (l_bits & 0xffffffffL)) != 0)
+ return x; // exp(NaN) = NaN
+ else
+ return negative ? -1.0 : x; // exp({+-inf}) = {+inf, -1}
+ }
+
+ if (x > EXP_LIMIT_H)
+ return Double.POSITIVE_INFINITY; // overflow
+ }
+
+ if (negative) // x <= -56 * ln(2)
+ return -1.0;
+ }
+
+ // argument reduction
+ if (h_bits > 0x3fd62e42L) // |x| > 0.5 * ln(2)
+ {
+ if (h_bits < 0x3ff0a2b2L) // |x| < 1.5 * ln(2)
+ {
+ if (negative)
+ {
+ hi = x + LN2_H;
+ lo = -LN2_L;
+ k = -1;
+ }
+ else
+ {
+ hi = x - LN2_H;
+ lo = LN2_L;
+ k = 1;
+ }
+ }
+ else
+ {
+ k = (int) (INV_LN2 * x + (negative ? - 0.5 : 0.5));
+ t = k;
+ hi = x - t * LN2_H;
+ lo = t * LN2_L;
+ }
+
+ x = hi - lo;
+ c = (hi - x) - lo;
+
+ }
+ else if (h_bits < 0x3c900000L) // |x| < 2^-54 return x
+ return x;
+ else
+ k = 0;
+
+ // x is now in primary range
+ hfx = 0.5 * x;
+ hxs = x * hfx;
+ r1 = 1.0 + hxs * (EXPM1_Q1
+ + hxs * (EXPM1_Q2
+ + hxs * (EXPM1_Q3
+ + hxs * (EXPM1_Q4
+ + hxs * EXPM1_Q5))));
+ t = 3.0 - r1 * hfx;
+ e = hxs * ((r1 - t) / (6.0 - x * t));
+
+ if (k == 0)
+ {
+ return x - (x * e - hxs); // c == 0
+ }
+ else
+ {
+ e = x * (e - c) - c;
+ e -= hxs;
+
+ if (k == -1)
+ return 0.5 * (x - e) - 0.5;
+
+ if (k == 1)
+ {
+ if (x < - 0.25)
+ return -2.0 * (e - (x + 0.5));
+ else
+ return 1.0 + 2.0 * (x - e);
+ }
+
+ if (k <= -2 || k > 56) // sufficient to return exp(x) - 1
+ {
+ y = 1.0 - (e - x);
+
+ bits = Double.doubleToLongBits(y);
+ h_bits = getHighDWord(bits);
+ l_bits = getLowDWord(bits);
+
+ h_bits += (k << 20); // add k to y's exponent
+
+ y = buildDouble(l_bits, h_bits);
+
+ return y - 1.0;
+ }
+
+ t = 1.0;
+ if (k < 20)
+ {
+ bits = Double.doubleToLongBits(t);
+ h_bits = 0x3ff00000L - (0x00200000L >> k);
+ l_bits = getLowDWord(bits);
+
+ t = buildDouble(l_bits, h_bits); // t = 1 - 2^(-k)
+ y = t - (e - x);
+
+ bits = Double.doubleToLongBits(y);
+ h_bits = getHighDWord(bits);
+ l_bits = getLowDWord(bits);
+
+ h_bits += (k << 20); // add k to y's exponent
+
+ y = buildDouble(l_bits, h_bits);
+ }
+ else
+ {
+ bits = Double.doubleToLongBits(t);
+ h_bits = (0x000003ffL - k) << 20;
+ l_bits = getLowDWord(bits);
+
+ t = buildDouble(l_bits, h_bits); // t = 2^(-k)
+
+ y = x - (e + t);
+ y += 1.0;
+
+ bits = Double.doubleToLongBits(y);
+ h_bits = getHighDWord(bits);
+ l_bits = getLowDWord(bits);
+
+ h_bits += (k << 20); // add k to y's exponent
+
+ y = buildDouble(l_bits, h_bits);
+ }
+ }
+
+ return y;
+ }
+
+ /**
* Take ln(a) (the natural log). The opposite of <code>exp()</code>. If the
* argument is NaN or negative, the result is NaN; if the argument is
* positive infinity, the result is positive infinity; and if the argument
@@ -1429,6 +2052,33 @@ public final strictfp class StrictMath
AT10 = 0.016285820115365782; // Long bits 0x3f90ad3ae322da11L.
/**
+ * Constants for computing {@link #cbrt(double)}.
+ */
+ private static final int
+ CBRT_B1 = 715094163, // B1 = (682-0.03306235651)*2**20
+ CBRT_B2 = 696219795; // B2 = (664-0.03306235651)*2**20
+
+ /**
+ * Constants for computing {@link #cbrt(double)}.
+ */
+ private static final double
+ CBRT_C = 5.42857142857142815906e-01, // Long bits 0x3fe15f15f15f15f1L
+ CBRT_D = -7.05306122448979611050e-01, // Long bits 0xbfe691de2532c834L
+ CBRT_E = 1.41428571428571436819e+00, // Long bits 0x3ff6a0ea0ea0ea0fL
+ CBRT_F = 1.60714285714285720630e+00, // Long bits 0x3ff9b6db6db6db6eL
+ CBRT_G = 3.57142857142857150787e-01; // Long bits 0x3fd6db6db6db6db7L
+
+ /**
+ * Constants for computing {@link #expm1(double)}
+ */
+ private static final double
+ EXPM1_Q1 = -3.33333333333331316428e-02, // Long bits 0xbfa11111111110f4L
+ EXPM1_Q2 = 1.58730158725481460165e-03, // Long bits 0x3f5a01a019fe5585L
+ EXPM1_Q3 = -7.93650757867487942473e-05, // Long bits 0xbf14ce199eaadbb7L
+ EXPM1_Q4 = 4.00821782732936239552e-06, // Long bits 0x3ed0cfca86e65239L
+ EXPM1_Q5 = -2.01099218183624371326e-07; // Long bits 0xbe8afdb76e09c32dL
+
+ /**
* Helper function for reducing an angle to a multiple of pi/2 within
* [-pi/4, pi/4].
*
diff --git a/java/lang/management/ManagementFactory.java b/java/lang/management/ManagementFactory.java
index 2de6d3b05..6e7af0f27 100644
--- a/java/lang/management/ManagementFactory.java
+++ b/java/lang/management/ManagementFactory.java
@@ -52,6 +52,8 @@ import gnu.java.lang.management.ThreadMXBeanImpl;
import java.util.ArrayList;
import java.util.List;
+import javax.management.NotCompliantMBeanException;
+
/**
* <p>
* Provides access to the system's management beans via a series
@@ -117,7 +119,16 @@ public class ManagementFactory
public static OperatingSystemMXBean getOperatingSystemMXBean()
{
if (osBean == null)
- osBean = new OperatingSystemMXBeanImpl();
+ try
+ {
+ osBean = new OperatingSystemMXBeanImpl();
+ }
+ catch (NotCompliantMBeanException e)
+ {
+ throw new InternalError("The GNU implementation of the " +
+ "operating system bean is not a " +
+ "compliant management bean.");
+ }
return osBean;
}
@@ -131,7 +142,16 @@ public class ManagementFactory
public static RuntimeMXBean getRuntimeMXBean()
{
if (runtimeBean == null)
- runtimeBean = new RuntimeMXBeanImpl();
+ try
+ {
+ runtimeBean = new RuntimeMXBeanImpl();
+ }
+ catch (NotCompliantMBeanException e)
+ {
+ throw new InternalError("The GNU implementation of the " +
+ "runtime bean is not a compliant " +
+ "management bean.");
+ }
return runtimeBean;
}
@@ -145,7 +165,16 @@ public class ManagementFactory
public static ClassLoadingMXBean getClassLoadingMXBean()
{
if (classLoadingBean == null)
- classLoadingBean = new ClassLoadingMXBeanImpl();
+ try
+ {
+ classLoadingBean = new ClassLoadingMXBeanImpl();
+ }
+ catch (NotCompliantMBeanException e)
+ {
+ throw new InternalError("The GNU implementation of the " +
+ "class loading bean is not a " +
+ "compliant management bean.");
+ }
return classLoadingBean;
}
@@ -159,7 +188,16 @@ public class ManagementFactory
public static ThreadMXBean getThreadMXBean()
{
if (threadBean == null)
- threadBean = new ThreadMXBeanImpl();
+ try
+ {
+ threadBean = new ThreadMXBeanImpl();
+ }
+ catch (NotCompliantMBeanException e)
+ {
+ throw new InternalError("The GNU implementation of the " +
+ "thread bean is not a compliant " +
+ "management bean.");
+ }
return threadBean;
}
@@ -173,7 +211,16 @@ public class ManagementFactory
public static MemoryMXBean getMemoryMXBean()
{
if (memoryBean == null)
- memoryBean = new MemoryMXBeanImpl();
+ try
+ {
+ memoryBean = new MemoryMXBeanImpl();
+ }
+ catch (NotCompliantMBeanException e)
+ {
+ throw new InternalError("The GNU implementation of the " +
+ "memory bean is not a compliant " +
+ "management bean.");
+ }
return memoryBean;
}
@@ -191,7 +238,16 @@ public class ManagementFactory
{
if (compilationBean == null &&
SystemProperties.getProperty("gnu.java.compiler.name") != null)
- compilationBean = new CompilationMXBeanImpl();
+ try
+ {
+ compilationBean = new CompilationMXBeanImpl();
+ }
+ catch (NotCompliantMBeanException e)
+ {
+ throw new InternalError("The GNU implementation of the " +
+ "compilation bean is not a compliant " +
+ "management bean.");
+ }
return compilationBean;
}
@@ -207,7 +263,16 @@ public class ManagementFactory
List poolBeans = new ArrayList();
String[] names = VMManagementFactory.getMemoryPoolNames();
for (int a = 0; a < names.length; ++a)
- poolBeans.add(new MemoryPoolMXBeanImpl(names[a]));
+ try
+ {
+ poolBeans.add(new MemoryPoolMXBeanImpl(names[a]));
+ }
+ catch (NotCompliantMBeanException e)
+ {
+ throw new InternalError("The GNU implementation of the " +
+ "memory pool bean, " + a + ", is " +
+ "not a compliant management bean.");
+ }
return poolBeans;
}
@@ -223,8 +288,17 @@ public class ManagementFactory
List managerBeans = new ArrayList();
String[] names = VMManagementFactory.getMemoryManagerNames();
for (int a = 0; a < names.length; ++a)
- managerBeans.add(new MemoryManagerMXBeanImpl(names[a]));
- managerBeans.add(getGarbageCollectorMXBeans());
+ try
+ {
+ managerBeans.add(new MemoryManagerMXBeanImpl(names[a]));
+ }
+ catch (NotCompliantMBeanException e)
+ {
+ throw new InternalError("The GNU implementation of the " +
+ "memory manager bean, " + a + ", is " +
+ "not a compliant management bean.");
+ }
+ managerBeans.addAll(getGarbageCollectorMXBeans());
return managerBeans;
}
@@ -240,7 +314,17 @@ public class ManagementFactory
List gcBeans = new ArrayList();
String[] names = VMManagementFactory.getGarbageCollectorNames();
for (int a = 0; a < names.length; ++a)
- gcBeans.add(new GarbageCollectorMXBeanImpl(names[a]));
+ try
+ {
+ gcBeans.add(new GarbageCollectorMXBeanImpl(names[a]));
+ }
+ catch (NotCompliantMBeanException e)
+ {
+ throw new InternalError("The GNU implementation of the " +
+ "garbage collector bean, " + a +
+ ", is not a compliant management " +
+ "bean.");
+ }
return gcBeans;
}
diff --git a/java/lang/management/MemoryMXBean.java b/java/lang/management/MemoryMXBean.java
index 33d211c9b..4d9e5ff1c 100644
--- a/java/lang/management/MemoryMXBean.java
+++ b/java/lang/management/MemoryMXBean.java
@@ -70,6 +70,34 @@ package java.lang.management;
* either change (either expanding or contracting) or stay
* the same.
* </p>
+ * <h2>Notifications</h2>
+ * <p>
+ * Implementations of this interface also conform to the
+ * {@link javax.management.NotificationEmitter} interface,
+ * and supply two notifications reflecting memory usage.
+ * These notifications occur when a usage threshold is
+ * exceeded; for more details of these, see the documentation
+ * of {@link MemoryPoolMXBean}. If threshold monitoring
+ * is supported, then a notification will be emitted each time
+ * the threshold is crossed. Another notification will not
+ * be emitted unless the usage level has dropped below the
+ * threshold again in the meantime.
+ * </p>
+ * <p>
+ * The emitted notifications are instances of
+ * {@link javax.management.Notification}, with a type of
+ * either
+ * {@link java.lang.management.MemoryNotificationInfo#MEMORY_THRESHOLD_EXCEEDED}
+ * or
+ * {@link java.lang.management.MemoryNotificationInfo#MEMORY_COLLECTION_THRESHOLD_EXCEEDED}
+ * (depending on whether the notification refers to the general
+ * usage threshold or the garbage collection threshold) and an instance
+ * of {@link java.lang.management.MemoryNotificationInfo} contained
+ * in the user data section. This is wrapped inside an instance
+ * of {@link javax.management.openmbean.CompositeData}, as explained
+ * in the documentation for
+ * {@link java.lang.management.MemoryNotificationInfo}.
+ * </p>
*
* @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.5
diff --git a/java/lang/management/MemoryNotificationInfo.java b/java/lang/management/MemoryNotificationInfo.java
new file mode 100644
index 000000000..adb38b06f
--- /dev/null
+++ b/java/lang/management/MemoryNotificationInfo.java
@@ -0,0 +1,215 @@
+/* MemoryNotificationInfo.java - Emitted memory notification info.
+ 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;
+
+import gnu.java.lang.management.MemoryMXBeanImpl;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.SimpleType;
+
+/**
+ * <p>
+ * Represents the content of a notification emitted by the
+ * {@link MemoryMXBean}. Such notifications are emitted when
+ * one of the memory pools exceeds its usage or collection
+ * usage threshold. This object contains the following information,
+ * representing the state of the pool at the time of the
+ * notification:
+ * </p>
+ * <ul>
+ * <li>The name of the pool.</li>
+ * <li>The memory usage of the pool at the time of notification.</li>
+ * <li>The number of times the pool has exceeded this particular
+ * threshold in the past.</li>
+ * </ul>
+ * <p>
+ * Two types of notification are emitted by the {@link MemoryMXBean}:
+ * one for exceeding the usage threshold and one for exceeding the
+ * collection usage threshold. The value returned by {@link #getCount()}
+ * is dependent on this type; if the threshold exceeded is the usage
+ * threshold, then the usage threshold count is returned. If, instead,
+ * the collection usage threshold is exceeded, then the collection usage
+ * threshold count is returned.
+ * </p>
+ * <p>
+ * This data is held in the user data part of the notification (returned
+ * by {@link javax.management.Notification#getUserData()}) encapsulated in
+ * a {@link javax.management.openmbean.CompositeData} object. The
+ * {@link #from(javax.management.openmbean.CompositeData)} method may be
+ * used to unwrap the value and obtain an instance of this class.
+ * </p>
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class MemoryNotificationInfo
+{
+
+ /**
+ * The type of notification emitted when the usage threshold is exceeded.
+ * After a notification is emitted, the usage level must drop below the
+ * threshold again before another notification is emitted. The value is
+ * <code>java.management.memory.threshold.exceeded</code>.
+ */
+ public static final String MEMORY_THRESHOLD_EXCEEDED =
+ "java.management.memory.threshold.exceeded";
+
+ /**
+ * The type of notification emitted when the collection usage threshold
+ * is exceeded, following a garbage collection cycle. The value is
+ * <code>java.management.memory.collection.threshold.exceeded</code>.
+ */
+ public static final String MEMORY_COLLECTION_THRESHOLD_EXCEEDED =
+ "java.management.memory.collection.threshold.exceeded";
+
+ /**
+ * The name of the memory pool which exceeded the threshold.
+ */
+ private String poolName;
+
+ /**
+ * The usage level of the memory pool at the time of notification.
+ */
+ private MemoryUsage usage;
+
+ /**
+ * The number of times the threshold has been crossed.
+ */
+ private long count;
+
+ /**
+ * Constructs a new {@link MemoryNotificationInfo} object using the
+ * specified pool name, usage level and threshold crossing count.
+ *
+ * @param poolName the name of the pool which has exceeded a threshold.
+ * @param usage the usage level of the pool at the time of notification.
+ * @param count the number of times the threshold has been crossed.
+ */
+ public MemoryNotificationInfo(String poolName, MemoryUsage usage, long count)
+ {
+ this.poolName = poolName;
+ this.usage = usage;
+ this.count = count;
+ }
+
+ /**
+ * <p>
+ * Returns a {@link MemoryNotificationInfo} instance using the values
+ * given in the supplied
+ * {@link javax.management.openmbean.CompositeData} object.
+ * The composite data instance should contain the following
+ * attributes with the specified types:
+ * </p>
+ * <table>
+ * <th><td>Name</td><td>Type</td></th>
+ * <tr><td>poolName</td><td>java.lang.String</td></tr>
+ * <tr><td>usage</td><td>javax.management.openmbean.CompositeData
+ * </td></tr>
+ * <tr><td>count</td><td>java.lang.Long</td></tr>
+ * </table>
+ * <p>
+ * The usage level is further described as:
+ * </p>
+ * <table>
+ * <th><td>Name</td><td>Type</td></th>
+ * <tr><td>init</td><td>java.lang.Long</td></tr>
+ * <tr><td>used</td><td>java.lang.Long</td></tr>
+ * <tr><td>committed</td><td>java.lang.Long</td></tr>
+ * <tr><td>max</td><td>java.lang.Long</td></tr>
+ * </table>
+ *
+ * @param data the composite data structure to take values from.
+ * @return a new instance containing the values from the
+ * composite data structure, or <code>null</code>
+ * if the data structure was also <code>null</code>.
+ * @throws IllegalArgumentException if the composite data structure
+ * does not match the structure
+ * outlined above.
+ */
+ public static MemoryNotificationInfo from(CompositeData data)
+ {
+ if (data == null)
+ return null;
+ CompositeType type = data.getCompositeType();
+ ThreadInfo.checkAttribute(type, "poolName", SimpleType.STRING);
+ ThreadInfo.checkAttribute(type, "usage", MemoryMXBeanImpl.usageType);
+ ThreadInfo.checkAttribute(type, "count", SimpleType.LONG);
+ MemoryUsage usage = MemoryUsage.from((CompositeData) data.get("usage"));
+ return new MemoryNotificationInfo(((String) data.get("poolName")),
+ usage,
+ ((Long) data.get("count")).longValue());
+ }
+
+ /**
+ * Returns the number of times the memory pool has crossed the usage
+ * threshold, as of the time of notification. If this is the notification
+ * represented by the type {@link #MEMORY_THRESHOLD_EXCEEDED}, then the
+ * count is the usage threshold count. If this is the notification
+ * represented by the type {@link #MEMORY_COLLECTION_THRESHOLD_EXCEEDED},
+ * then the count is the collection usage threshold count.
+ *
+ * @return the number of times the appropriate threshold has been crossed.
+ */
+ public long getCount()
+ {
+ return count;
+ }
+
+ /**
+ * Returns the name of the pool which has crossed a threshold.
+ *
+ * @return the name of the pool.
+ */
+ public String getPoolName()
+ {
+ return poolName;
+ }
+
+ /**
+ * Returns the usage levels at the time of notification.
+ *
+ * @return the usage levels.
+ */
+ public MemoryUsage getUsage()
+ {
+ return usage;
+ }
+
+}
+
diff --git a/java/lang/management/MemoryPoolMXBean.java b/java/lang/management/MemoryPoolMXBean.java
index 29b438c29..5b04c64d3 100644
--- a/java/lang/management/MemoryPoolMXBean.java
+++ b/java/lang/management/MemoryPoolMXBean.java
@@ -157,6 +157,14 @@ public interface MemoryPoolMXBean
MemoryUsage getPeakUsage();
/**
+ * Returns the type of memory used by this pool. This can be
+ * either heap or non-heap memory.
+ *
+ * @return the type of this pool.
+ */
+ String getType();
+
+ /**
* Returns memory usage statistics for the current memory usage
* of the pool. The return value may be <code>null</code> if
* this pool is no longer valid. Obtaining these values is
diff --git a/java/lang/management/MemoryUsage.java b/java/lang/management/MemoryUsage.java
index 29aa1f9f1..3c2a4cba6 100644
--- a/java/lang/management/MemoryUsage.java
+++ b/java/lang/management/MemoryUsage.java
@@ -37,6 +37,9 @@ exception statement from your version. */
package java.lang.management;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.SimpleType;
/**
* <p>
* Retains information on the usage of a particular memory
@@ -146,6 +149,48 @@ public class MemoryUsage
}
/**
+ * <p>
+ * Returns a {@link MemoryUsage} instance using the values
+ * given in the supplied
+ * {@link javax.management.openmbean.CompositeData} object.
+ * The composite data instance should contain the following
+ * attributes:
+ * </p>
+ * <ul>
+ * <li>init</li>
+ * <li>used</li>
+ * <li>committed</li>
+ * <li>max</li>
+ * </ul>
+ * <p>
+ * All should have the type, <code>java.lang.Long</code>.
+ * </p>
+ *
+ * @param data the composite data structure to take values from.
+ * @return a new instance containing the values from the
+ * composite data structure, or <code>null</code>
+ * if the data structure was also <code>null</code>.
+ * @throws IllegalArgumentException if the composite data structure
+ * does not match the structure
+ * outlined above, or the values
+ * are invalid.
+ */
+ public static MemoryUsage from(CompositeData data)
+ {
+ if (data == null)
+ return null;
+ CompositeType type = data.getCompositeType();
+ ThreadInfo.checkAttribute(type, "init", SimpleType.LONG);
+ ThreadInfo.checkAttribute(type, "used", SimpleType.LONG);
+ ThreadInfo.checkAttribute(type, "committed", SimpleType.LONG);
+ ThreadInfo.checkAttribute(type, "max", SimpleType.LONG);
+ return new MemoryUsage(((Long) data.get("init")).longValue(),
+ ((Long) data.get("used")).longValue(),
+ ((Long) data.get("committed")).longValue(),
+ ((Long) data.get("max")).longValue());
+ }
+
+ /**
* Returns the amount of memory committed for use by this
* memory pool (in bytes). This amount is guaranteed to
* be available, unlike the maximum.
diff --git a/java/lang/management/ThreadInfo.java b/java/lang/management/ThreadInfo.java
index ebb2e8382..4bf35a4cb 100644
--- a/java/lang/management/ThreadInfo.java
+++ b/java/lang/management/ThreadInfo.java
@@ -37,6 +37,13 @@ exception statement from your version. */
package java.lang.management;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+
/**
* <p>
* A class which maintains information about a particular
@@ -83,9 +90,19 @@ public class ThreadInfo
{
/**
- * The thread which this instance concerns.
+ * The id of the thread which this instance concerns.
+ */
+ private long threadId;
+
+ /**
+ * The name of the thread which this instance concerns.
+ */
+ private String threadName;
+
+ /**
+ * The state of the thread which this instance concerns.
*/
- private Thread thread;
+ private String threadState;
/**
* The number of times the thread has been blocked.
@@ -100,17 +117,24 @@ public class ThreadInfo
private long blockedTime;
/**
- * The monitor lock on which this thread is blocked
- * (if any).
+ * The name of the monitor lock on which this thread
+ * is blocked (if any).
*/
- private Object lock;
+ private String lockName;
/**
- * The thread which owns the monitor lock on which this
- * thread is blocked, or <code>null</code> if there is
- * no owner.
+ * The id of the thread which owns the monitor lock on
+ * which this thread is blocked, or <code>-1</code>
+ * if there is no owner.
*/
- private Thread lockOwner;
+ private long lockOwnerId;
+
+ /**
+ * The name of the thread which owns the monitor lock on
+ * which this thread is blocked, or <code>null</code>
+ * if there is no owner.
+ */
+ private String lockOwnerName;
/**
* The number of times the thread has been in a waiting
@@ -176,11 +200,60 @@ public class ThreadInfo
long waitedTime, boolean isInNative, boolean isSuspended,
StackTraceElement[] trace)
{
- this.thread = thread;
+ 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,
+ trace);
+ }
+
+ /**
+ * Constructs a new {@link ThreadInfo} corresponding
+ * to the thread details specified.
+ *
+ * @param threadId the id of the thread on which this
+ * new instance will be based.
+ * @param threadName the name of the thread on which
+ * this new instance will be based.
+ * @param threadState the state of the thread on which
+ * this new instance will be based.
+ * @param blockedCount the number of times the thread
+ * has been blocked.
+ * @param blockedTime the accumulated number of milliseconds
+ * the specified thread has been blocked
+ * (only used with contention monitoring enabled)
+ * @param lockName the name of the monitor lock the thread is waiting for
+ * (only used if blocked)
+ * @param lockOwnerId the id of the thread which owns the monitor
+ * lock, or <code>-1</code> if it doesn't have an owner
+ * (only used if blocked)
+ * @param lockOwnerName the name of the thread which owns the monitor
+ * lock, or <code>null</code> if it doesn't have an
+ * owner (only used if blocked)
+ * @param waitedCount the number of times the thread has been in a
+ * waiting state.
+ * @param waitedTime the accumulated number of milliseconds the
+ * specified thread has been waiting
+ * (only used with contention monitoring enabled)
+ * @param isInNative true if the thread is in a native method.
+ * @param isSuspended true if the thread is suspended.
+ * @param trace the stack trace of the thread to a pre-determined
+ * depth (see VMThreadMXBeanImpl)
+ */
+ private ThreadInfo(long threadId, String threadName, String threadState,
+ long blockedCount, long blockedTime, String lockName,
+ long lockOwnerId, String lockOwnerName, long waitedCount,
+ long waitedTime, boolean isInNative, boolean isSuspended,
+ StackTraceElement[] trace)
+ {
+ this.threadId = threadId;
+ this.threadName = threadName;
+ this.threadState = threadState;
this.blockedCount = blockedCount;
this.blockedTime = blockedTime;
- this.lock = lock;
- this.lockOwner = lockOwner;
+ this.lockName = lockName;
+ this.lockOwnerId = lockOwnerId;
+ this.lockOwnerName = lockOwnerName;
this.waitedCount = waitedCount;
this.waitedTime = waitedTime;
this.isInNative = isInNative;
@@ -189,6 +262,145 @@ public class ThreadInfo
}
/**
+ * Checks for an attribute in a {@link CompositeData} structure
+ * with the correct type.
+ *
+ * @param ctype the composite data type to check.
+ * @param name the name of the attribute.
+ * @param type the type to check for.
+ * @throws IllegalArgumentException if the attribute is absent
+ * or of the wrong type.
+ */
+ static void checkAttribute(CompositeType ctype, String name,
+ OpenType type)
+ throws IllegalArgumentException
+ {
+ OpenType foundType = ctype.getType(name);
+ if (foundType == null)
+ throw new IllegalArgumentException("Could not find a field named " +
+ name);
+ if (!(foundType.equals(type)))
+ throw new IllegalArgumentException("Field " + name + " is not of " +
+ "type " + type.getClassName());
+ }
+
+ /**
+ * <p>
+ * Returns a {@link ThreadInfo} instance using the values
+ * given in the supplied
+ * {@link javax.management.openmbean.CompositeData} object.
+ * The composite data instance should contain the following
+ * attributes with the specified types:
+ * </p>
+ * <table>
+ * <th><td>Name</td><td>Type</td></th>
+ * <tr><td>threadId</td><td>java.lang.Long</td></tr>
+ * <tr><td>threadName</td><td>java.lang.String</td></tr>
+ * <tr><td>threadState</td><td>java.lang.String</td></tr>
+ * <tr><td>suspended</td><td>java.lang.Boolean</td></tr>
+ * <tr><td>inNative</td><td>java.lang.Boolean</td></tr>
+ * <tr><td>blockedCount</td><td>java.lang.Long</td></tr>
+ * <tr><td>blockedTime</td><td>java.lang.Long</td></tr>
+ * <tr><td>waitedCount</td><td>java.lang.Long</td></tr>
+ * <tr><td>waitedTime</td><td>java.lang.Long</td></tr>
+ * <tr><td>lockName</td><td>java.lang.String</td></tr>
+ * <tr><td>lockOwnerId</td><td>java.lang.Long</td></tr>
+ * <tr><td>lockOwnerName</td><td>java.lang.String</td></tr>
+ * <tr><td>stackTrace</td><td>javax.management.openmbean.CompositeData[]
+ * </td></tr>
+ * </table>
+ * <p>
+ * The stack trace is further described as:
+ * </p>
+ * <table>
+ * <th><td>Name</td><td>Type</td></th>
+ * <tr><td>className</td><td>java.lang.String</td></tr>
+ * <tr><td>methodName</td><td>java.lang.String</td></tr>
+ * <tr><td>fileName</td><td>java.lang.String</td></tr>
+ * <tr><td>lineNumber</td><td>java.lang.Integer</td></tr>
+ * <tr><td>nativeMethod</td><td>java.lang.Boolean</td></tr>
+ * </table>
+ *
+ * @param data the composite data structure to take values from.
+ * @return a new instance containing the values from the
+ * composite data structure, or <code>null</code>
+ * if the data structure was also <code>null</code>.
+ * @throws IllegalArgumentException if the composite data structure
+ * does not match the structure
+ * outlined above.
+ */
+ public static ThreadInfo from(CompositeData data)
+ {
+ if (data == null)
+ return null;
+ CompositeType type = data.getCompositeType();
+ checkAttribute(type, "threadId", SimpleType.LONG);
+ checkAttribute(type, "threadName", SimpleType.STRING);
+ checkAttribute(type, "threadState", SimpleType.STRING);
+ checkAttribute(type, "suspended", SimpleType.BOOLEAN);
+ checkAttribute(type, "inNative", SimpleType.BOOLEAN);
+ checkAttribute(type, "blockedCount", SimpleType.LONG);
+ checkAttribute(type, "blockedTime", SimpleType.LONG);
+ checkAttribute(type, "waitedCount", SimpleType.LONG);
+ checkAttribute(type, "waitedTime", SimpleType.LONG);
+ checkAttribute(type, "lockName", SimpleType.STRING);
+ checkAttribute(type, "lockOwnerId", SimpleType.LONG);
+ checkAttribute(type, "lockOwnerName", SimpleType.STRING);
+ try
+ {
+ CompositeType seType =
+ new CompositeType(StackTraceElement.class.getName(),
+ "An element of a stack trace",
+ new String[] { "className", "methodName",
+ "fileName", "lineNumber",
+ "nativeMethod"
+ },
+ new String[] { "Name of the class",
+ "Name of the method",
+ "Name of the source code file",
+ "Line number",
+ "True if this is a native method"
+ },
+ new OpenType[] {
+ SimpleType.STRING, SimpleType.STRING,
+ SimpleType.STRING, SimpleType.INTEGER,
+ SimpleType.BOOLEAN
+ });
+ checkAttribute(type, "stackTrace", new ArrayType(1, seType));
+ }
+ catch (OpenDataException e)
+ {
+ throw new IllegalStateException("Something went wrong in creating " +
+ "the composite data type for the " +
+ "stack trace element.", e);
+ }
+ CompositeData[] dTraces = (CompositeData[]) data.get("stackTrace");
+ StackTraceElement[] traces = new StackTraceElement[dTraces.length];
+ for (int a = 0; a < dTraces.length; ++a)
+ /* FIXME: We can't use the boolean as there is no available
+ constructor. */
+ traces[a] =
+ new StackTraceElement((String) dTraces[a].get("className"),
+ (String) dTraces[a].get("methodName"),
+ (String) dTraces[a].get("fileName"),
+ ((Integer)
+ dTraces[a].get("lineNumber")).intValue());
+ return new ThreadInfo(((Long) data.get("threadId")).longValue(),
+ (String) data.get("threadName"),
+ (String) data.get("threadState"),
+ ((Long) data.get("blockedCount")).longValue(),
+ ((Long) data.get("blockedTime")).longValue(),
+ (String) data.get("lockName"),
+ ((Long) data.get("lockOwnerId")).longValue(),
+ (String) data.get("lockOwnerName"),
+ ((Long) data.get("waitedCount")).longValue(),
+ ((Long) data.get("waitedTime")).longValue(),
+ ((Boolean) data.get("inNative")).booleanValue(),
+ ((Boolean) data.get("suspended")).booleanValue(),
+ traces);
+ }
+
+ /**
* Returns the number of times this thread has been
* in the {@link java.lang.Thread.State#BLOCKED} state.
* A thread enters this state when it is waiting to
@@ -272,10 +484,9 @@ public class ThreadInfo
*/
public String getLockName()
{
- if (thread.getState().equals("BLOCKED"))
+ if (threadState.equals("BLOCKED"))
return null;
- return lock.getClass().getName() + "@" +
- Integer.toHexString(System.identityHashCode(lock));
+ return lockName;
}
/**
@@ -291,11 +502,9 @@ public class ThreadInfo
*/
public long getLockOwnerId()
{
- if (thread.getState().equals("BLOCKED"))
- return -1;
- if (lockOwner == null)
+ if (threadState.equals("BLOCKED"))
return -1;
- return lockOwner.getId();
+ return lockOwnerId;
}
/**
@@ -311,11 +520,9 @@ public class ThreadInfo
*/
public String getLockOwnerName()
{
- if (thread.getState().equals("BLOCKED"))
- return null;
- if (lockOwner == null)
+ if (threadState.equals("BLOCKED"))
return null;
- return lockOwner.getName();
+ return lockOwnerName;
}
/**
@@ -350,7 +557,7 @@ public class ThreadInfo
*/
public long getThreadId()
{
- return thread.getId();
+ return threadId;
}
/**
@@ -361,7 +568,7 @@ public class ThreadInfo
*/
public String getThreadName()
{
- return thread.getName();
+ return threadName;
}
/**
@@ -372,7 +579,7 @@ public class ThreadInfo
*/
public String getThreadState()
{
- return thread.getState();
+ return threadState;
}
/**
@@ -480,17 +687,17 @@ public class ThreadInfo
*/
public String toString()
{
- String state = thread.getState();
return getClass().getName() +
- "[id=" + thread.getId() +
- ", name=" + thread.getName() +
- ", state=" + state +
+ "[id=" + threadId +
+ ", name=" + threadName +
+ ", state=" + threadState +
", blockedCount=" + blockedCount +
", waitedCount=" + waitedCount +
", isInNative=" + isInNative +
", isSuspended=" + isSuspended +
- (state.equals("BLOCKED") ? ", lock=" + lock +
- ", lockOwner=" + lockOwner : "") +
+ (threadState.equals("BLOCKED") ?
+ ", lockOwnerId=" + lockOwnerId +
+ ", lockOwnerName=" + lockOwnerName : "") +
"]";
}
diff --git a/java/math/BigDecimal.java b/java/math/BigDecimal.java
index 3a2dd8417..bca9b12c2 100644
--- a/java/math/BigDecimal.java
+++ b/java/math/BigDecimal.java
@@ -1,5 +1,5 @@
/* java.math.BigDecimal -- Arbitrary precision decimals.
- Copyright (C) 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2003, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -266,8 +266,10 @@ public class BigDecimal extends Number implements Comparable
long mantissa = bits & mantMask;
long exponent = (bits >>> mantissaBits) & expMask;
boolean denormal = exponent == 0;
+
// Correct the exponent for the bias.
exponent -= denormal ? 1022 : 1023;
+
// Now correct the exponent to account for the bits to the right
// of the decimal.
exponent -= mantissaBits;
@@ -748,6 +750,19 @@ public class BigDecimal extends Number implements Comparable
}
/**
+ * Performs division, if the resulting quotient requires rounding
+ * (has a nonterminating decimal expansion),
+ * an ArithmeticException is thrown.
+ * #see divide(BigDecimal, int, int)
+ * @since 1.5
+ */
+ public BigDecimal divide(BigDecimal divisor)
+ throws ArithmeticException, IllegalArgumentException
+ {
+ return divide(divisor, scale, ROUND_UNNECESSARY);
+ }
+
+ /**
* Returns a BigDecimal whose value is the remainder in the quotient
* this / val. This is obtained by
* subtract(divideToIntegralValue(val).multiply(val)).
@@ -760,7 +775,7 @@ public class BigDecimal extends Number implements Comparable
{
return subtract(divideToIntegralValue(val).multiply(val));
}
-
+
/**
* Returns a BigDecimal array, the first element of which is the integer part
* of this / val, and the second element of which is the remainder of
@@ -994,84 +1009,13 @@ public class BigDecimal extends Number implements Comparable
{
if (precision == 0)
{
- if (intVal.compareTo(BigInteger.TEN.pow(18)) == 1)
- precision = numDigitsInBigInteger(intVal);
- else
- precision = numDigitsInLong(intVal.longValue());
- }
+ String s = intVal.toString();
+ precision = s.length() - (( s.charAt(0) == '-' ) ? 1 : 0);
+ }
return precision;
}
/**
- * This method is used to determine the precision of BigIntegers with 19 or
- * more digits.
- * @param b the BigInteger
- * @return the number of digits in <code>b</code>
- */
- int numDigitsInBigInteger(BigInteger b)
- {
- int i = 19;
- BigInteger comp = BigInteger.TEN.pow(i);
- while (b.compareTo(comp) >= 0)
- comp = BigInteger.TEN.pow(++i);
-
- return i;
- }
-
- /**
- * This method determines the number of digits in the long value l.
- * @param l1 the long value
- * @return the number of digits in l
- */
- private static int numDigitsInLong(long l1)
- {
- long l = l1 >= 0 ? l1 : -l1;
- // We divide up the range in a binary fashion, this first if
- // takes care of numbers with 1 to 9 digits.
- if (l < 1000000000L)
- {
- // This if is for numbers with 1 to 5 digits.
- if (l < 100000L)
- {
- if (l < 100L)
- return (l < 10L) ? 1 : 2;
- if (l < 10000L)
- return (l < 1000L) ? 3 : 4;
- return 5;
- }
- // Here we handle numbers with 6 to 9 digits.
- if (l < 10000000L)
- return (l < 1000000L) ? 6 : 7;
- return (l < 100000000L) ? 8 : 9;
- }
- // If we are at this point that means we didn't enter the loop for
- // numbers with 1 to 9 digits, so our number has 10 to 19 digits.
- // This first if handles numbers with 10 to 14 digits.
- if (l < 100000000000000L)
- {
- // This handles numbers with 10 to 12 digits.
- if (l < 1000000000000L)
- {
- if (l < 100000000000L)
- return (l < 10000000000L) ? 10 : 11;
- return 12;
- }
- // This handles numbers with 13 or 14 digits.
- return (l < 10000000000000L) ? 13 : 14;
- }
- // Finally we handle numbers with 15 to 19 digits.
- if (l < 100000000000000000L)
- {
- // 15 to 17 digits.
- if (l < 1000000000000000L)
- return 15;
- return (l < 10000000000000000L) ? 16 : 17;
- }
- // 18 or 19 digits.
- return (l < 1000000000000000000L) ? 18 : 19;
- }
-
- /**
* Returns the String representation of this BigDecimal, using scientific
* notation if necessary. The following steps are taken to generate
* the result:
@@ -1097,15 +1041,14 @@ public class BigDecimal extends Number implements Comparable
if (scale == 0)
return bigStr;
- // This is the adjusted exponent described above.
- int adjExp = -scale + (numDigitsInLong(intVal.longValue()) - 1);
+ boolean negative = (bigStr.charAt(0) == '-');
+ int point = bigStr.length() - scale - (negative ? 1 : 0);
+
StringBuilder val = new StringBuilder();
- if (scale >= 0 && adjExp >= -6)
+ if (scale >= 0 && (point - 1) >= -6)
{
- // Convert to character form without scientific notation.
- boolean negative = (bigStr.charAt(0) == '-');
- int point = bigStr.length() - scale - (negative ? 1 : 0);
+ // Convert to character form without scientific notation.
if (point <= 0)
{
// Zeros need to be prepended to the StringBuilder.
@@ -1136,12 +1079,12 @@ public class BigDecimal extends Number implements Comparable
// If there is more than one digit in the unscaled value we put a
// decimal after the first digit.
if (bigStr.length() > 1)
- val.insert(1, '.');
- // And then append 'E' and the exponent (adjExp).
+ val.insert( ( negative ? 2 : 1 ), '.');
+ // And then append 'E' and the exponent = (point - 1).
val.append('E');
- if (adjExp >= 0)
+ if (point - 1 >= 0)
val.append('+');
- val.append(adjExp);
+ val.append( point - 1 );
}
return val.toString();
}
@@ -1163,15 +1106,16 @@ public class BigDecimal extends Number implements Comparable
if (scale == 0)
return bigStr;
+ boolean negative = (bigStr.charAt(0) == '-');
+ int point = bigStr.length() - scale - (negative ? 1 : 0);
+
// This is the adjusted exponent described above.
- int adjExp = -scale + (numDigitsInLong(intVal.longValue()) - 1);
+ int adjExp = point - 1;
StringBuilder val = new StringBuilder();
if (scale >= 0 && adjExp >= -6)
{
// Convert to character form without scientific notation.
- boolean negative = (bigStr.charAt(0) == '-');
- int point = bigStr.length() - scale - (negative ? 1 : 0);
if (point <= 0)
{
// Zeros need to be prepended to the StringBuilder.
@@ -1238,7 +1182,7 @@ public class BigDecimal extends Number implements Comparable
val.append('0');
}
else if (bigStr.length() > dot)
- val.insert(dot, '.');
+ val.insert(dot + (negative ? 1 : 0), '.');
// And then append 'E' and the exponent (adjExp).
val.append('E');
@@ -1400,6 +1344,10 @@ public class BigDecimal extends Number implements Comparable
public BigDecimal setScale (int scale, int roundingMode)
throws ArithmeticException, IllegalArgumentException
{
+ // NOTE: The 1.5 JRE doesn't throw this, ones prior to it do and
+ // the spec says it should. Nevertheless, if 1.6 doesn't fix this
+ // we should consider removing it.
+ if( scale < 0 ) throw new ArithmeticException("Scale parameter < 0.");
return divide (ONE, scale, roundingMode);
}
diff --git a/java/math/BigInteger.java b/java/math/BigInteger.java
index b57cf607e..3715cbbba 100644
--- a/java/math/BigInteger.java
+++ b/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.
@@ -197,8 +197,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 +237,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;
@@ -1589,24 +1606,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/java/net/Inet6Address.java b/java/net/Inet6Address.java
index 0d62fe919..8d834a6fd 100644
--- a/java/net/Inet6Address.java
+++ b/java/net/Inet6Address.java
@@ -39,13 +39,16 @@ exception statement from your version. */
package java.net;
import java.util.Arrays;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.IOException;
/*
* Written using on-line Java Platform 1.4 API Specification and
* RFC 1884 (http://www.ietf.org/rfc/rfc1884.txt)
*
* @author Michael Koch
- * @status Believed complete and correct.
+ * @status Updated to 1.5. Serialization compatibility is tested.
*/
public final class Inet6Address extends InetAddress
{
@@ -57,6 +60,39 @@ public final class Inet6Address extends InetAddress
byte[] ipaddress;
/**
+ * The scope ID, if any.
+ * @since 1.5
+ * @serial
+ */
+ private int scope_id;
+
+ /**
+ * The scope ID, if any.
+ * @since 1.5
+ * @serial
+ */
+ private boolean scope_id_set;
+
+ /**
+ * Whether ifname is set or not.
+ * @since 1.5
+ * @serial
+ */
+ private boolean scope_ifname_set;
+
+ /**
+ * Name of the network interface, used only by the serialization methods
+ * @since 1.5
+ * @serial
+ */
+ private String ifname;
+
+ /**
+ * Scope network interface, or <code>null</code>.
+ */
+ private transient NetworkInterface nif;
+
+ /**
* Create an Inet6Address object
*
* @param addr The IP address
@@ -67,6 +103,10 @@ public final class Inet6Address extends InetAddress
super(addr, host);
// Super constructor clones the addr. Get a reference to the clone.
this.ipaddress = this.addr;
+ ifname = null;
+ scope_ifname_set = scope_id_set = false;
+ scope_id = 0;
+ nif = null;
}
/**
@@ -199,6 +239,75 @@ public final class Inet6Address extends InetAddress
}
/**
+ * Creates a scoped Inet6Address where the scope has an integer id.
+ *
+ * @throws UnkownHostException if the address is an invalid number of bytes.
+ * @since 1.5
+ */
+ public static Inet6Address getByAddress(String host, byte[] addr,
+ int scopeId)
+ throws UnknownHostException
+ {
+ if( addr.length != 16 )
+ throw new UnknownHostException("Illegal address length: " + addr.length
+ + " bytes.");
+ Inet6Address ip = new Inet6Address( addr, host );
+ ip.scope_id = scopeId;
+ ip.scope_id_set = true;
+ return ip;
+ }
+
+ /**
+ * Creates a scoped Inet6Address where the scope is a given
+ * NetworkInterface.
+ *
+ * @throws UnkownHostException if the address is an invalid number of bytes.
+ * @since 1.5
+ */
+ public static Inet6Address getByAddress(String host, byte[] addr,
+ NetworkInterface nif)
+ throws UnknownHostException
+ {
+ if( addr.length != 16 )
+ throw new UnknownHostException("Illegal address length: " + addr.length
+ + " bytes.");
+ Inet6Address ip = new Inet6Address( addr, host );
+ ip.nif = nif;
+
+ return ip;
+ }
+
+ /**
+ * Returns the <code>NetworkInterface</code> of the address scope
+ * if it is a scoped address and the scope is given in the form of a
+ * NetworkInterface.
+ * (I.e. the address was created using the
+ * getByAddress(String, byte[], NetworkInterface) method)
+ * Otherwise this method returns <code>null</code>.
+ * @since 1.5
+ */
+ public NetworkInterface getScopedInterface()
+ {
+ return nif;
+ }
+
+ /**
+ * Returns the scope ID of the address scope if it is a scoped adress using
+ * an integer to identify the scope.
+ *
+ * Otherwise this method returns 0.
+ * @since 1.5
+ */
+ public int getScopeId()
+ {
+ // check scope_id_set because some JDK-serialized objects seem to have
+ // scope_id set to a nonzero value even when scope_id_set == false
+ if( scope_id_set )
+ return scope_id;
+ return 0;
+ }
+
+ /**
* Returns the IP address string in textual presentation
*/
public String getHostAddress()
@@ -214,12 +323,17 @@ public final class Inet6Address extends InetAddress
sbuf.append(Integer.toHexString(x));
}
+ if( nif != null )
+ sbuf.append( "%" + nif.getName() );
+ else if( scope_id_set )
+ sbuf.append( "%" + scope_id );
return sbuf.toString();
}
/**
* Returns a hashcode for this IP address
+ * (The hashcode is independent of scope)
*/
public int hashCode()
{
@@ -234,10 +348,23 @@ public final class Inet6Address extends InetAddress
if (! (obj instanceof Inet6Address))
return false;
- // this.ipaddress is never set in this class except to
- // the value of the super class' addr. The super classes
- // equals(Object) will do the compare.
- return super.equals(obj);
+ Inet6Address ip = (Inet6Address)obj;
+ if (ipaddress.length != ip.ipaddress.length)
+ return false;
+
+ for (int i = 0; i < ip.ipaddress.length; i++)
+ if (ipaddress[i] != ip.ipaddress[i])
+ return false;
+
+ if( ip.nif != null && nif != null )
+ return nif.equals( ip.nif );
+ if( ip.nif != nif )
+ return false;
+ if( ip.scope_id_set != scope_id_set )
+ return false;
+ if( scope_id_set )
+ return (scope_id == ip.scope_id);
+ return true;
}
/**
@@ -258,4 +385,38 @@ public final class Inet6Address extends InetAddress
return true;
}
+
+ /**
+ * Required for 1.5-compatible serialization.
+ * @since 1.5
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ try
+ {
+ if( scope_ifname_set )
+ nif = NetworkInterface.getByName( ifname );
+ }
+ catch( SocketException se )
+ {
+ // FIXME: Ignore this? or throw an IOException?
+ }
+ }
+
+ /**
+ * Required for 1.5-compatible serialization.
+ * @since 1.5
+ */
+ private void writeObject(ObjectOutputStream s)
+ throws IOException
+ {
+ if( nif != null )
+ {
+ ifname = nif.getName();
+ scope_ifname_set = true;
+ }
+ s.defaultWriteObject();
+ }
}
diff --git a/java/net/URL.java b/java/net/URL.java
index 85037b3e7..ed7decc79 100644
--- a/java/net/URL.java
+++ b/java/net/URL.java
@@ -545,8 +545,7 @@ public final class URL implements Serializable
*/
public Object getContent(Class[] classes) throws IOException
{
- // FIXME: implement this
- return getContent();
+ return openConnection().getContent(classes);
}
/**
diff --git a/java/net/URLStreamHandler.java b/java/net/URLStreamHandler.java
index ed9509221..9a5d73ad0 100644
--- a/java/net/URLStreamHandler.java
+++ b/java/net/URLStreamHandler.java
@@ -369,13 +369,11 @@ public abstract class URLStreamHandler
}
/**
- * Provides the default equals calculation. May be overidden by handlers for
- * other protocols that have different requirements for equals(). This method
- * requires that none of its arguments is null. This is guaranteed by the
- * fact that it is only called by java.net.URL class.
+ * This is the default method for computing whether two URLs are
+ * equivalent. This method assumes that neither URL is null.
*
* @param url1 An URL object
- * @param url2 An URL object
+ * @param url2 Another URL object
*
* @return True if both given URLs are equal, false otherwise.
*/
@@ -383,16 +381,21 @@ public abstract class URLStreamHandler
{
// This comparison is very conservative. It assumes that any
// field can be null.
- return (url1.getPort() == url2.getPort()
+ int port1 = url1.getPort();
+ if (port1 == -1)
+ port1 = url1.getDefaultPort();
+ int port2 = url2.getPort();
+ if (port2 == -1)
+ port2 = url2.getDefaultPort();
+ // Note that we don't bother checking the 'authority'; it is
+ // redundant.
+ return (port1 == port2
&& ((url1.getProtocol() == null && url2.getProtocol() == null)
|| (url1.getProtocol() != null
&& url1.getProtocol().equals(url2.getProtocol())))
&& ((url1.getUserInfo() == null && url2.getUserInfo() == null)
|| (url1.getUserInfo() != null
&& url1.getUserInfo().equals(url2.getUserInfo())))
- && ((url1.getAuthority() == null && url2.getAuthority() == null)
- || (url1.getAuthority() != null
- && url1.getAuthority().equals(url2.getAuthority())))
&& ((url1.getHost() == null && url2.getHost() == null)
|| (url1.getHost() != null && url1.getHost().equals(url2.getHost())))
&& ((url1.getPath() == null && url2.getPath() == null)
diff --git a/java/nio/DirectByteBufferImpl.java b/java/nio/DirectByteBufferImpl.java
index 53bb668aa..8c907f597 100644
--- a/java/nio/DirectByteBufferImpl.java
+++ b/java/nio/DirectByteBufferImpl.java
@@ -232,7 +232,8 @@ abstract class DirectByteBufferImpl extends ByteBuffer
private ByteBuffer duplicate(boolean readOnly)
{
int pos = position();
- reset();
+ if (this.mark != -1)
+ reset();
int mark = position();
position(pos);
DirectByteBufferImpl result;
diff --git a/java/nio/channels/SelectionKey.java b/java/nio/channels/SelectionKey.java
index 5219b6bff..9723faf52 100644
--- a/java/nio/channels/SelectionKey.java
+++ b/java/nio/channels/SelectionKey.java
@@ -1,5 +1,5 @@
/* SelectionKey.java --
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -60,7 +60,7 @@ public abstract class SelectionKey
/**
* Attaches obj to the key and returns the old attached object.
*/
- public final Object attach(Object obj)
+ public final synchronized Object attach(Object obj)
{
Object old = attached;
attached = obj;
@@ -70,7 +70,7 @@ public abstract class SelectionKey
/**
* Returns the object attached to the key.
*/
- public final Object attachment()
+ public final synchronized Object attachment()
{
return attached;
}
diff --git a/java/nio/channels/spi/AbstractSelectionKey.java b/java/nio/channels/spi/AbstractSelectionKey.java
index 5ab8468bf..02d09ce10 100644
--- a/java/nio/channels/spi/AbstractSelectionKey.java
+++ b/java/nio/channels/spi/AbstractSelectionKey.java
@@ -1,5 +1,5 @@
/* AbstractSelectionKey.java --
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -57,7 +57,7 @@ public abstract class AbstractSelectionKey extends SelectionKey
/**
* Cancels this key.
*/
- public final void cancel()
+ public final synchronized void cancel()
{
if (isValid())
{
@@ -71,7 +71,7 @@ public abstract class AbstractSelectionKey extends SelectionKey
*
* @return true if this key is valid, false otherwise
*/
- public final boolean isValid()
+ public final synchronized boolean isValid()
{
return ! cancelled;
}
diff --git a/java/security/AccessControlContext.java b/java/security/AccessControlContext.java
index 3b51e9412..ffcfc0e41 100644
--- a/java/security/AccessControlContext.java
+++ b/java/security/AccessControlContext.java
@@ -89,12 +89,30 @@ public final class AccessControlContext
public AccessControlContext(AccessControlContext acc,
DomainCombiner combiner)
{
+ AccessControlContext acc2 = null;
SecurityManager sm = System.getSecurityManager ();
if (sm != null)
{
- sm.checkPermission (new SecurityPermission ("createAccessControlContext"));
+ Permission perm =
+ new SecurityPermission ("createAccessControlContext");
+
+ // The default SecurityManager.checkPermission(perm) just calls
+ // AccessController.checkPermission(perm) which in turn just
+ // calls AccessController.getContext().checkPermission(perm).
+ // This means AccessController.getContext() is called twice,
+ // once for the security check and once by us. It's a very
+ // expensive call (on gcj at least) so if we're using the
+ // default security manager we avoid this duplication.
+ if (sm.getClass() == SecurityManager.class)
+ {
+ acc2 = AccessController.getContext ();
+ acc2.checkPermission (perm);
+ }
+ else
+ sm.checkPermission (perm);
}
- AccessControlContext acc2 = AccessController.getContext();
+ if (acc2 == null)
+ acc2 = AccessController.getContext ();
protectionDomains = combiner.combine (acc2.protectionDomains,
acc.protectionDomains);
this.combiner = combiner;
diff --git a/java/security/AlgorithmParameterGenerator.java b/java/security/AlgorithmParameterGenerator.java
index e33fbaf81..e2a17d4bf 100644
--- a/java/security/AlgorithmParameterGenerator.java
+++ b/java/security/AlgorithmParameterGenerator.java
@@ -40,6 +40,7 @@ package java.security;
import gnu.java.security.Engine;
+import java.lang.reflect.InvocationTargetException;
import java.security.spec.AlgorithmParameterSpec;
/**
@@ -97,26 +98,29 @@ public class AlgorithmParameterGenerator
* Returns a new <code>AlgorithmParameterGenerator</code> instance which
* generates algorithm parameters for the specified algorithm.
*
- * @param algorithm
- * the name of algorithm to use.
+ * @param algorithm the name of algorithm to use.
* @return the new instance.
- * @throws NoSuchAlgorithmException
- * if <code>algorithm</code> is not implemented by any provider.
+ * @throws NoSuchAlgorithmException if <code>algorithm</code> is not
+ * implemented by any provider.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static AlgorithmParameterGenerator getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
try
{
return getInstance(algorithm, p[i]);
}
- catch (NoSuchAlgorithmException e)
- {
- // Ignore.
- }
-
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
@@ -124,27 +128,27 @@ public class AlgorithmParameterGenerator
* Returns a new <code>AlgorithmParameterGenerator</code> instance which
* generates algorithm parameters for the specified algorithm.
*
- * @param algorithm
- * the name of algorithm to use.
- * @param provider
- * the name of the {@link Provider} to use.
+ * @param algorithm the name of algorithm to use.
+ * @param provider the name of the {@link Provider} to use.
* @return the new instance.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the named provider.
- * @throws NoSuchProviderException
- * if the named provider was not found.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * named provider.
+ * @throws NoSuchProviderException if the named provider was not found.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
public static AlgorithmParameterGenerator getInstance(String algorithm,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("Illegal provider");
-
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
@@ -152,38 +156,50 @@ public class AlgorithmParameterGenerator
* Returns a new <code>AlgorithmParameterGenerator</code> instance which
* generates algorithm parameters for the specified algorithm.
*
- * @param algorithm
- * the name of algorithm to use.
- * @param provider
- * the {@link Provider} to use.
+ * @param algorithm the name of algorithm to use.
+ * @param provider the {@link Provider} to use.
* @return the new instance.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by {@link Provider}.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by
+ * {@link Provider}.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
* @since 1.4
* @see Provider
*/
public static AlgorithmParameterGenerator getInstance(String algorithm,
Provider provider)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
-
+ StringBuilder sb = new StringBuilder()
+ .append("AlgorithmParameterGenerator for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new AlgorithmParameterGenerator(
- (AlgorithmParameterGeneratorSpi) Engine.getInstance(
- ALGORITHM_PARAMETER_GENERATOR, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(ALGORITHM_PARAMETER_GENERATOR,
+ algorithm,
+ provider);
+ return new AlgorithmParameterGenerator((AlgorithmParameterGeneratorSpi) spi,
+ provider,
+ algorithm);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
/** @return the {@link Provider} of this generator. */
diff --git a/java/security/AlgorithmParameters.java b/java/security/AlgorithmParameters.java
index c4655aefa..14a28df21 100644
--- a/java/security/AlgorithmParameters.java
+++ b/java/security/AlgorithmParameters.java
@@ -41,6 +41,7 @@ package java.security;
import gnu.java.security.Engine;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
@@ -91,106 +92,115 @@ public class AlgorithmParameters
/**
* Returns a new instance of <code>AlgorithmParameters</code> representing
* the specified algorithm parameters.
+ * <p>
+ * The returned <code>AlgorithmParameters</code> must still be initialized
+ * with an <code>init()</code> method.
*
- * <p>The returned <code>AlgorithmParameters</code> must still be initialized
- * with an <code>init()</code> method.</p>
- *
- * @param algorithm
- * the algorithm to use.
+ * @param algorithm the algorithm to use.
* @return the new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by any provider.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by any
+ * provider.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static AlgorithmParameters getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
-
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
try
{
return getInstance(algorithm, p[i]);
}
- catch (NoSuchAlgorithmException e)
- {
- // Ignore this.
- }
-
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
/**
* Returns a new instance of <code>AlgorithmParameters</code> representing
* the specified algorithm parameters from a named provider.
+ * <p>
+ * The returned <code>AlgorithmParameters</code> must still be intialized
+ * with an <code>init()</code> method.
+ * </p>
*
- * <p>The returned <code>AlgorithmParameters</code> must still be intialized
- * with an <code>init()</code> method.</p>
- *
- * @param algorithm
- * the algorithm to use.
- * @param provider
- * the name of the {@link Provider} to use.
+ * @param algorithm the algorithm to use.
+ * @param provider the name of the {@link Provider} to use.
* @return the new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the named provider.
- * @throws NoSuchProviderException
- * if the named provider was not found.
- * @throws IllegalArgumentException
- * if <code>provider</code> is <code>null</code> or is an empty
- * string.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * named provider.
+ * @throws NoSuchProviderException if the named provider was not found.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
- public static AlgorithmParameters getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ public static AlgorithmParameters getInstance(String algorithm,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("Illegal provider");
-
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
/**
* Returns a new instance of <code>AlgorithmParameters</code> representing
* the specified algorithm parameters from the specified {@link Provider}.
+ * <p>
+ * The returned <code>AlgorithmParameters</code> must still be intialized
+ * with an <code>init()</code> method.
*
- * <p>The returned <code>AlgorithmParameters</code> must still be intialized
- * with an <code>init()</code> method.</p>
- *
- * @param algorithm
- * the algorithm to use.
- * @param provider
- * the {@link Provider} to use.
+ * @param algorithm the algorithm to use.
+ * @param provider the {@link Provider} to use.
* @return the new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the {@link Provider}.
- * @throws IllegalArgumentException
- * if <code>provider</code> is <code>null</code>.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * {@link Provider}.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
* @since 1.4
*/
public static AlgorithmParameters getInstance(String algorithm,
Provider provider)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
-
+ StringBuilder sb = new StringBuilder("AlgorithmParameters for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new AlgorithmParameters((AlgorithmParametersSpi)
- Engine.getInstance(ALGORITHM_PARAMETERS, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(ALGORITHM_PARAMETERS, algorithm, provider);
+ return new AlgorithmParameters((AlgorithmParametersSpi) spi,
+ provider,
+ algorithm);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
/** @return the provider of this parameter object. */
diff --git a/java/security/KeyFactory.java b/java/security/KeyFactory.java
index edb2a87da..914975d77 100644
--- a/java/security/KeyFactory.java
+++ b/java/security/KeyFactory.java
@@ -40,6 +40,7 @@ package java.security;
import gnu.java.security.Engine;
+import java.lang.reflect.InvocationTargetException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
@@ -93,26 +94,29 @@ public class KeyFactory
* Returns a new instance of <code>KeyFactory</code> representing the
* specified key factory.
*
- * @param algorithm
- * the name of algorithm to use.
+ * @param algorithm the name of algorithm to use.
* @return a new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by any provider.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by any
+ * provider.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static KeyFactory getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
try
{
return getInstance(algorithm, p[i]);
}
- catch (NoSuchAlgorithmException e)
- {
- // Ignore.
- }
-
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
@@ -120,29 +124,26 @@ public class KeyFactory
* Returns a new instance of <code>KeyFactory</code> representing the
* specified key factory from the specified provider.
*
- * @param algorithm
- * the name of algorithm to use.
- * @param provider
- * the name of the provider to use.
+ * @param algorithm the name of algorithm to use.
+ * @param provider the name of the provider to use.
* @return a new instance repesenting the desired algorithm.
- * @throws IllegalArgumentException
- * if <code>provider</code> is <code>null</code> or is an empty
- * string.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the named provider.
- * @throws NoSuchProviderException
- * if the named provider was not found.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * named provider.
+ * @throws NoSuchProviderException if the named provider was not found.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
public static KeyFactory getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("Illegal provider");
-
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
@@ -150,38 +151,44 @@ public class KeyFactory
* Returns a new instance of <code>KeyFactory</code> representing the
* specified key factory from the designated {@link Provider}.
*
- * @param algorithm
- * the name of algorithm to use.
- * @param provider
- * the {@link Provider} to use.
+ * @param algorithm the name of algorithm to use.
+ * @param provider the {@link Provider} to use.
* @return a new instance repesenting the desired algorithm.
- * @throws IllegalArgumentException
- * if <code>provider</code> is <code>null</code>.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by {@link Provider}.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by
+ * {@link Provider}.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
* @since 1.4
* @see Provider
*/
public static KeyFactory getInstance(String algorithm, Provider provider)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
-
+ StringBuilder sb = new StringBuilder("KeyFactory for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new KeyFactory((KeyFactorySpi)
- Engine.getInstance(KEY_FACTORY, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(KEY_FACTORY, algorithm, provider);
+ return new KeyFactory((KeyFactorySpi) spi, provider, algorithm);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
- }
+ cause = x;
+ }
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
/**
diff --git a/java/security/KeyPairGenerator.java b/java/security/KeyPairGenerator.java
index 357d7a75f..6974035fd 100644
--- a/java/security/KeyPairGenerator.java
+++ b/java/security/KeyPairGenerator.java
@@ -40,6 +40,7 @@ package java.security;
import gnu.java.security.Engine;
+import java.lang.reflect.InvocationTargetException;
import java.security.spec.AlgorithmParameterSpec;
/**
@@ -90,28 +91,29 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi
* Returns a new instance of <code>KeyPairGenerator</code> which generates
* key-pairs for the specified algorithm.
*
- * @param algorithm
- * the name of the algorithm to use.
+ * @param algorithm the name of the algorithm to use.
* @return a new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by any provider.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by any
+ * provider.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static KeyPairGenerator getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(algorithm, p[i]);
- }
- catch (NoSuchAlgorithmException e)
- {
- // Ignored.
- }
- }
-
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
@@ -119,23 +121,26 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi
* Returns a new instance of <code>KeyPairGenerator</code> which generates
* key-pairs for the specified algorithm from a named provider.
*
- * @param algorithm
- * the name of the algorithm to use.
- * @param provider
- * the name of a {@link Provider} to use.
+ * @param algorithm the name of the algorithm to use.
+ * @param provider the name of a {@link Provider} to use.
* @return a new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the named provider.
- * @throws NoSuchProviderException
- * if the named provider was not found.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * named provider.
+ * @throws NoSuchProviderException if the named provider was not found.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
public static KeyPairGenerator getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
@@ -148,10 +153,11 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi
* @param provider
* the {@link Provider} to use.
* @return a new insatnce repesenting the desired algorithm.
- * @throws IllegalArgumentException
- * if <code>provider</code> is <code>null</code>.
* @throws NoSuchAlgorithmException
* if the algorithm is not implemented by the {@link Provider}.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
* @since 1.4
* @see Provider
*/
@@ -159,20 +165,27 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi
Provider provider)
throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
-
- Object o = null;
+ StringBuilder sb = new StringBuilder("KeyPairGenerator for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] ");
+ Object o;
try
{
o = Engine.getInstance(KEY_PAIR_GENERATOR, algorithm, provider);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ Throwable cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
+ sb.append("could not be created");
+ NoSuchAlgorithmException y = new NoSuchAlgorithmException(sb.toString());
+ y.initCause(cause);
+ throw y;
}
-
- KeyPairGenerator result = null;
+ KeyPairGenerator result;
if (o instanceof KeyPairGenerator)
{
result = (KeyPairGenerator) o;
@@ -180,7 +193,11 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi
}
else if (o instanceof KeyPairGeneratorSpi)
result = new DummyKeyPairGenerator((KeyPairGeneratorSpi) o, algorithm);
-
+ else
+ {
+ sb.append("is of an unexpected Type: ").append(o.getClass().getName());
+ throw new NoSuchAlgorithmException(sb.toString());
+ }
result.provider = provider;
return result;
}
diff --git a/java/security/KeyStore.java b/java/security/KeyStore.java
index 8681d8265..3015e3295 100644
--- a/java/security/KeyStore.java
+++ b/java/security/KeyStore.java
@@ -43,6 +43,7 @@ import gnu.java.security.Engine;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
import java.security.cert.CertificateException;
import java.util.Date;
import java.util.Enumeration;
@@ -108,105 +109,100 @@ public class KeyStore
this.type = type;
}
- // Class methods.
- // ------------------------------------------------------------------------
-
- /**
- * Gets an instance of the KeyStore class representing
- * the specified keystore. If the type is not
- * found then, it throws KeyStoreException.
- *
- * @param type the type of keystore to choose
- * @return a KeyStore repesenting the desired type
- * @throws KeyStoreException if the type of keystore is not implemented
- * by providers or the implementation cannot be instantiated.
+ /**
+ * Returns an instance of a <code>KeyStore</code> representing the specified
+ * type, from the first provider that implements it.
+ *
+ * @param type the type of keystore to create.
+ * @return a <code>KeyStore</code> repesenting the desired type.
+ * @throws KeyStoreException if the designated type of is not implemented by
+ * any provider, or the implementation could not be instantiated.
+ * @throws IllegalArgumentException if <code>type</code> is
+ * <code>null</code> or is an empty string.
*/
public static KeyStore getInstance(String type) throws KeyStoreException
{
Provider[] p = Security.getProviders();
-
+ KeyStoreException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(type, p[i]);
- }
- catch (KeyStoreException e)
- {
- // Ignore.
- }
- }
-
+ try
+ {
+ return getInstance(type, p[i]);
+ }
+ catch (KeyStoreException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new KeyStoreException(type);
}
- /**
- * Gets an instance of the KeyStore class representing
- * the specified key store from the specified provider.
- * If the type is not found then, it throws KeyStoreException.
- * If the provider is not found, then it throws
- * NoSuchProviderException.
- *
- * @param type the type of keystore to choose
- * @param provider the provider name
- * @return a KeyStore repesenting the desired type
- * @throws KeyStoreException if the type of keystore is not
- * implemented by the given provider
- * @throws NoSuchProviderException if the provider is not found
- * @throws IllegalArgumentException if the provider string is
- * null or empty
+ /**
+ * Returns an instance of a <code>KeyStore</code> representing the specified
+ * type, from the named provider.
+ *
+ * @param type the type of keystore to create.
+ * @param provider the name of the provider to use.
+ * @return a <code>KeyStore</code> repesenting the desired type.
+ * @throws KeyStoreException if the designated type is not implemented by the
+ * given provider.
+ * @throws NoSuchProviderException if the provider is not found.
+ * @throws IllegalArgumentException if either <code>type</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
public static KeyStore getInstance(String type, String provider)
throws KeyStoreException, NoSuchProviderException
{
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("Illegal provider");
-
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(type, p);
}
- /**
- * Gets an instance of the KeyStore class representing
- * the specified key store from the specified provider.
- * If the type is not found then, it throws KeyStoreException.
- * If the provider is not found, then it throws
- * NoSuchProviderException.
- *
- * @param type the type of keystore to choose
- * @param provider the keystore provider
- * @return a KeyStore repesenting the desired type
- * @throws KeyStoreException if the type of keystore is not
- * implemented by the given provider
- * @throws IllegalArgumentException if the provider object is null
+ /**
+ * Returns an instance of a <code>KeyStore</code> representing the specified
+ * type, from the specified provider.
+ *
+ * @param type the type of keystore to create.
+ * @param provider the provider to use.
+ * @return a <code>KeyStore</code> repesenting the desired type.
+ * @throws KeyStoreException if the designated type is not implemented by the
+ * given provider.
+ * @throws IllegalArgumentException if either <code>type</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>type</code> is an empty string.
* @since 1.4
*/
public static KeyStore getInstance(String type, Provider provider)
- throws KeyStoreException
+ throws KeyStoreException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
+ Throwable cause;
try
{
- return new KeyStore(
- (KeyStoreSpi) Engine.getInstance(KEY_STORE, type, provider),
- provider, type);
+ Object spi = Engine.getInstance(KEY_STORE, type, provider);
+ return new KeyStore((KeyStoreSpi) spi, provider, type);
}
- catch (NoSuchAlgorithmException nsae)
+ catch (NoSuchAlgorithmException x)
{
- throw new KeyStoreException(type);
+ cause = x;
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new KeyStoreException(type);
+ cause = x.getCause() != null ? x.getCause() : x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new KeyStoreException(type);
+ cause = x;
}
+ KeyStoreException x = new KeyStoreException(type);
+ x.initCause(cause);
+ throw x;
}
/**
diff --git a/java/security/MessageDigest.java b/java/security/MessageDigest.java
index b817759f5..5fa07cf2a 100644
--- a/java/security/MessageDigest.java
+++ b/java/security/MessageDigest.java
@@ -39,6 +39,8 @@ package java.security;
import gnu.java.security.Engine;
+import java.lang.reflect.InvocationTargetException;
+
/**
* Message digests are secure one-way hash functions that take arbitrary-sized
* data and output a fixed-length hash value.
@@ -72,28 +74,29 @@ public abstract class MessageDigest extends MessageDigestSpi
* Returns a new instance of <code>MessageDigest</code> representing the
* specified algorithm.
*
- * @param algorithm
- * the name of the digest algorithm to use.
+ * @param algorithm the name of the digest algorithm to use.
* @return a new instance representing the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by any provider.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by any
+ * provider.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static MessageDigest getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(algorithm, p[i]);
- }
- catch (NoSuchAlgorithmException ignored)
- {
- // Ignore.
- }
- }
-
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
@@ -101,29 +104,26 @@ public abstract class MessageDigest extends MessageDigestSpi
* Returns a new instance of <code>MessageDigest</code> representing the
* specified algorithm from a named provider.
*
- * @param algorithm
- * the name of the digest algorithm to use.
- * @param provider
- * the name of the provider to use.
+ * @param algorithm the name of the digest algorithm to use.
+ * @param provider the name of the provider to use.
* @return a new instance representing the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the named provider.
- * @throws NoSuchProviderException
- * if the named provider was not found.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * named provider.
+ * @throws NoSuchProviderException if the named provider was not found.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
public static MessageDigest getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
- if (provider != null)
- provider = provider.trim();
-
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("Illegal provider");
-
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
@@ -131,39 +131,43 @@ public abstract class MessageDigest extends MessageDigestSpi
* Returns a new instance of <code>MessageDigest</code> representing the
* specified algorithm from a designated {@link Provider}.
*
- * @param algorithm
- * the name of the digest algorithm to use.
- * @param provider
- * the {@link Provider} to use.
+ * @param algorithm the name of the digest algorithm to use.
+ * @param provider the {@link Provider} to use.
* @return a new instance representing the desired algorithm.
- * @throws IllegalArgumentException
- * if <code>provider</code> is <code>null</code>.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by {@link Provider}.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by
+ * {@link Provider}.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
* @since 1.4
* @see Provider
*/
public static MessageDigest getInstance(String algorithm, Provider provider)
throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
-
- MessageDigest result = null;
- Object o = null;
+ StringBuilder sb = new StringBuilder("MessageDigest for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] ");
+ Object o;
try
{
o = Engine.getInstance(MESSAGE_DIGEST, algorithm, provider);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ Throwable cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
+ sb.append("could not be created");
+ NoSuchAlgorithmException y = new NoSuchAlgorithmException(sb.toString());
+ y.initCause(cause);
+ throw y;
}
-
+ MessageDigest result;
if (o instanceof MessageDigestSpi)
- {
- result = new DummyMessageDigest((MessageDigestSpi) o, algorithm);
- }
+ result = new DummyMessageDigest((MessageDigestSpi) o, algorithm);
else if (o instanceof MessageDigest)
{
result = (MessageDigest) o;
@@ -171,7 +175,8 @@ public abstract class MessageDigest extends MessageDigestSpi
}
else
{
- throw new NoSuchAlgorithmException(algorithm);
+ sb.append("is of an unexpected Type: ").append(o.getClass().getName());
+ throw new NoSuchAlgorithmException(sb.toString());
}
result.provider = provider;
return result;
diff --git a/java/security/Provider.java b/java/security/Provider.java
index 4ffaa55bc..ea1dd9d3f 100644
--- a/java/security/Provider.java
+++ b/java/security/Provider.java
@@ -1,5 +1,5 @@
/* Provider.java -- Security provider information
- Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2002, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,20 +41,19 @@ import java.io.Serializable;
import java.util.Properties;
/**
- * This class represents a Java security architecture service provider.
- * The services provided by a such a provider can range from security
- * algorithms to key generation.
+ * This class represents a Java security architecture service provider. The
+ * services provided by a such a provider can range from security algorithms to
+ * key generation.
* <p>
- * Providers are installed by name and version number. There is one
- * standard provider supplied with the class library. This is the
- * "GNU" provider, which can also be accessed by the alias "SUN" for
- * compatibility with the JDK.
- *
- * @version 0.0
- *
+ * Providers are installed by name and version number. See the static
+ * initializer of the {@link java.security.Security} class for the default
+ * security providers installed by this class library.
+ *
* @author Aaron M. Renn (arenn@urbanophile.com)
*/
-public abstract class Provider extends Properties implements Serializable
+public abstract class Provider
+ extends Properties
+ implements Serializable
{
private static final long serialVersionUID = -4298000515446427739L;
@@ -119,36 +118,34 @@ public abstract class Provider extends Properties implements Serializable
}
/**
- * Sets the key property to have the specified value.
+ * Maps a key property to a designated value.
* <p>
- * <bold>NOT IMPLEMENTED YET</bold>[
- * First, if there is a security manager, its <code>checkSecurityAccess</code>
- * method is called with the string "putProviderProperty."+name, where name is
- * the provider name, to see if it's ok to set this provider's property
- * values.
- * If the default implementation of <code>checkSecurityAccess</code> is used
- * (that is, that method is not overriden), then this results in a call to the
- * security manager's <code>checkPermission</code> method with a
- * <code>SecurityPermission("putProviderProperty."+name)</code>
- * permission.<br>]
- *
+ * If there is an installed {@link SecurityManager} object in the underlying
+ * VM, its {@link SecurityManager#checkSecurityAccess(String)} method is
+ * called with the string <code>"putProviderProperty." + name</code>, where
+ * <code>name</code> is this provider's name. For the default implementation
+ * this translates into a {@link SecurityManager#checkPermission(Permission)}
+ * for a <code>SecurityPermission("putProviderProperty." + name)</code>.
+ *
* @param key The property key.
* @param value The property value.
- *
* @return The previous value of the specified property (<code>key</code>),
* or <code>null</code> if it did not have one.
- * @throws SecurityException If a security manager exists and its
- * {@link java.lang.SecurityManager.checkSecurityAccess(java.lang.String)}
- * method denies access to set property values.
+ * @throws SecurityException If a security manager is installed and its
+ * {@link SecurityManager#checkSecurityAccess(String)} method
+ * disallows adding properties at run-time.
* @since Classpath 0.4+cvs, JDK 1.2
- * @see java.lang.Object.equals(Object)
- * @see java.util.Hashtable.get(Object)
+ * @see java.lang.Object#equals(Object)
+ * @see java.util.Hashtable#get(Object)
*/
public Object put(Object key, Object value)
{
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("putProviderProperty." + this.name);
return super.put(toCanonicalKey(key), value);
}
-
+
// overrides same in java.util.Hashtable
public Object get(Object key)
{
@@ -157,25 +154,45 @@ public abstract class Provider extends Properties implements Serializable
/**
* This method removes the specified key entry (and its associated value)
- * from the property mapping list.
+ * from the property mapping collection.
+ * <p>
+ * If there is an installed {@link SecurityManager} object in the underlying
+ * VM, its {@link SecurityManager#checkSecurityAccess(String)} method is
+ * called with the string <code>"removeProviderProperty." + name</code>, where
+ * <code>name</code> is this provider's name. For the default implementation
+ * this translates into a {@link SecurityManager#checkPermission(Permission)}
+ * for a <code>SecurityPermission("removeProviderProperty." + name)</code>.
*
* @param key The key to remove
- *
* @return The previous value for this key, or <code>null</code> if no
* previous value.
*/
public Object remove(Object key)
{
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("removeProviderProperty." + this.name);
return super.remove(toCanonicalKey(key));
}
/**
- * This method clears the entire property list such that it no longer
+ * This method clears the entire property collection such that it no longer
* contains the properties used to look up the services provided by
- * the <code>Provider</code>.
+ * this <code>Provider</code>.
+ * <p>
+ * If there is an installed {@link SecurityManager} object in the underlying
+ * VM, its {@link SecurityManager#checkSecurityAccess(String)} method is
+ * called with the string <code>"clearProviderProperties." + name</code>,
+ * where <code>name</code> is this provider's name. For the default
+ * implementation this translates into a
+ * {@link SecurityManager#checkPermission(Permission)} for a
+ * <code>SecurityPermission("clearProviderProperties." + name)</code>.
*/
public void clear()
{
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("clearProviderProperties." + this.name);
super.clear();
}
@@ -191,12 +208,11 @@ public abstract class Provider extends Properties implements Serializable
return (getClass().getName() + ": name=" + getName() + " version=" +
version);
}
-
+
private Object toCanonicalKey(Object key)
{
if (key.getClass().isAssignableFrom(String.class)) // is it ours?
return ((String) key).toUpperCase(); // use default locale
- else
- return key;
+ return key;
}
}
diff --git a/java/security/SecureRandom.java b/java/security/SecureRandom.java
index d403d4964..005f4670e 100644
--- a/java/security/SecureRandom.java
+++ b/java/security/SecureRandom.java
@@ -45,6 +45,7 @@ import gnu.java.security.jce.prng.Sha160RandomSpi;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
@@ -187,101 +188,106 @@ public class SecureRandom extends Random
this.algorithm = algorithm;
}
- // Class methods.
- // ------------------------------------------------------------------------
-
/**
- * Returns an instance of a SecureRandom. It creates the class from
- * the first provider that implements it.
- *
+ * Returns an instance of a <code>SecureRandom</code> from the first provider
+ * that implements it.
+ *
* @param algorithm The algorithm name.
- * @return A new SecureRandom implementing the given algorithm.
- * @throws NoSuchAlgorithmException If no installed provider implements
- * the given algorithm.
+ * @return A new <code>SecureRandom</code> implementing the given algorithm.
+ * @throws NoSuchAlgorithmException If no installed provider implements the
+ * given algorithm.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static SecureRandom getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
-
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(algorithm, p[i]);
- }
- catch (NoSuchAlgorithmException e)
- {
- // Ignore.
- }
- }
-
- // None found.
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
/**
- * Returns an instance of a SecureRandom. It creates the class
- * for the specified algorithm from the named provider.
- *
+ * Returns an instance of a <code>SecureRandom</code> for the specified
+ * algorithm from the named provider.
+ *
* @param algorithm The algorithm name.
- * @param provider The provider name.
- * @return A new SecureRandom implementing the chosen algorithm.
+ * @param provider The provider name.
+ * @return A new <code>SecureRandom</code> implementing the chosen
+ * algorithm.
* @throws NoSuchAlgorithmException If the named provider does not implement
- * the algorithm, or if the implementation cannot be
- * instantiated.
- * @throws NoSuchProviderException If no provider named
- * <code>provider</code> is currently installed.
- * @throws IllegalArgumentException If <code>provider</code> is null
- * or is empty.
+ * the algorithm, or if the implementation cannot be instantiated.
+ * @throws NoSuchProviderException If no provider named <code>provider</code>
+ * is currently installed.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
public static SecureRandom getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("Illegal provider");
-
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
/**
- * Returns an instance of a SecureRandom. It creates the class for
- * the specified algorithm from the given provider.
- *
- * @param algorithm The SecureRandom algorithm to create.
- * @param provider The provider to get the instance from.
- * @throws NoSuchAlgorithmException If the algorithm cannot be found, or
- * if the class cannot be instantiated.
- * @throws IllegalArgumentException If <code>provider</code> is null.
+ * Returns an instance of a <code>SecureRandom</code> for the specified
+ * algorithm from the given provider.
+ *
+ * @param algorithm The <code>SecureRandom</code> algorithm to create.
+ * @param provider The provider to use.
+ * @throws NoSuchAlgorithmException If the algorithm cannot be found, or if
+ * the class cannot be instantiated.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static SecureRandom getInstance(String algorithm, Provider provider)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
+ StringBuilder sb = new StringBuilder("SecureRandom for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new SecureRandom((SecureRandomSpi)
- Engine.getInstance(SECURE_RANDOM, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(SECURE_RANDOM, algorithm, provider);
+ return new SecureRandom((SecureRandomSpi) spi, provider, algorithm);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
/**
Returns the provider being used by the current SecureRandom class.
@@ -374,14 +380,9 @@ public class SecureRandom extends Random
if (numBits == 0)
return 0;
- byte[] tmp = new byte[numBits / 8 + (1 * (numBits % 8))];
-
- secureRandomSpi.engineNextBytes(tmp);
- randomBytesUsed += tmp.length;
- counter++;
-
+ byte[] tmp = new byte[(numBits + 7) / 8];
+ this.nextBytes(tmp);
int ret = 0;
-
for (int i = 0; i < tmp.length; i++)
ret |= (tmp[i] & 0xFF) << (8 * i);
diff --git a/java/security/Signature.java b/java/security/Signature.java
index 845a77a8b..6f65f3a89 100644
--- a/java/security/Signature.java
+++ b/java/security/Signature.java
@@ -40,6 +40,7 @@ package java.security;
import gnu.java.security.Engine;
+import java.lang.reflect.InvocationTargetException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.spec.AlgorithmParameterSpec;
@@ -127,28 +128,29 @@ public abstract class Signature extends SignatureSpi
* Returns an instance of <code>Signature</code> representing the specified
* signature.
*
- * @param algorithm
- * the algorithm to use.
+ * @param algorithm the algorithm to use.
* @return a new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by any provider.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by any
+ * provider.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static Signature getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(algorithm, p[i]);
- }
- catch (NoSuchAlgorithmException e)
- {
- // Ignored.
- }
- }
-
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
@@ -156,28 +158,26 @@ public abstract class Signature extends SignatureSpi
* Returns an instance of <code>Signature</code> representing the specified
* signature from the named provider.
*
- * @param algorithm
- * the algorithm to use.
- * @param provider
- * the name of the provider to use.
+ * @param algorithm the algorithm to use.
+ * @param provider the name of the provider to use.
* @return a new instance repesenting the desired algorithm.
- * @throws IllegalArgumentException if <code>provider</code> is
- * <code>null</code> or is an empty string.
- * @throws NoSuchProviderException
- * if the named provider was not found.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the named provider.
+ * @throws NoSuchProviderException if the named provider was not found.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * named provider.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
public static Signature getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("Illegal provider");
-
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
@@ -185,35 +185,41 @@ public abstract class Signature extends SignatureSpi
* Returns an instance of <code>Signature</code> representing the specified
* signature from the specified {@link Provider}.
*
- * @param algorithm
- * the algorithm to use.
- * @param provider
- * the {@link Provider} to use.
+ * @param algorithm the algorithm to use.
+ * @param provider the {@link Provider} to use.
* @return a new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the {@link Provider}.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * {@link Provider}.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static Signature getInstance(String algorithm, Provider provider)
throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
-
- Signature result = null;
- Object o = null;
+ StringBuilder sb = new StringBuilder("Signature algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] ");
+ Object o;
try
{
o = Engine.getInstance(SIGNATURE, algorithm, provider);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ Throwable cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
+ sb.append("could not be created");
+ NoSuchAlgorithmException y = new NoSuchAlgorithmException(sb.toString());
+ y.initCause(cause);
+ throw y;
}
-
+ Signature result;
if (o instanceof SignatureSpi)
- {
- result = new DummySignature((SignatureSpi) o, algorithm);
- }
+ result = new DummySignature((SignatureSpi) o, algorithm);
else if (o instanceof Signature)
{
result = (Signature) o;
@@ -221,7 +227,8 @@ public abstract class Signature extends SignatureSpi
}
else
{
- throw new NoSuchAlgorithmException(algorithm);
+ sb.append("is of an unexpected Type: ").append(o.getClass().getName());
+ throw new NoSuchAlgorithmException(sb.toString());
}
result.provider = provider;
return result;
diff --git a/java/security/cert/CertPathBuilder.java b/java/security/cert/CertPathBuilder.java
index f6965205f..519ed2b6c 100644
--- a/java/security/cert/CertPathBuilder.java
+++ b/java/security/cert/CertPathBuilder.java
@@ -40,6 +40,7 @@ package java.security.cert;
import gnu.java.security.Engine;
+import java.lang.reflect.InvocationTargetException;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
@@ -111,50 +112,54 @@ public class CertPathBuilder
}
/**
- * Get an instance of a named CertPathBuilder, from the first provider
- * that implements it.
- *
- * @param algorithm The name of the CertPathBuilder to create.
+ * Returns an instance of a named <code>CertPathBuilder</code> from the
+ * first provider that implements it.
+ *
+ * @param algorithm The name of the <code>CertPathBuilder</code> to create.
* @return The new instance.
- * @throws NoSuchAlgorithmException If no installed provider
- * implements the named algorithm.
+ * @throws NoSuchAlgorithmException If no installed provider implements the
+ * named algorithm.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static CertPathBuilder getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
-
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(algorithm, p[i]);
- }
- catch (NoSuchAlgorithmException e)
- {
- // Ignored.
- }
- }
-
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
/**
- * Get an instance of a named CertPathBuilder from the named
+ * Returns an instance of a named <code>CertPathBuilder</code> from a named
* provider.
- *
- * @param algorithm The name of the CertPathBuilder to create.
- * @param provider The name of the provider from which to get the
- * implementation.
+ *
+ * @param algorithm The name of the <code>CertPathBuilder</code> to create.
+ * @param provider The name of the provider to use.
* @return The new instance.
- * @throws NoSuchAlgorithmException If no installed provider
- * implements the named algorithm.
- * @throws NoSuchProviderException If the named provider does not
- * exist.
+ * @throws NoSuchAlgorithmException If no installed provider implements the
+ * named algorithm.
+ * @throws NoSuchProviderException If the named provider does not exist.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static CertPathBuilder getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
@@ -162,41 +167,47 @@ public class CertPathBuilder
}
/**
- * Get an instance of a named CertPathBuilder from the specified
- * provider.
- *
- * @param algorithm The name of the CertPathBuilder to create.
- * @param provider The provider from which to get the implementation.
+ * Returns an instance of a named <code>CertPathBuilder</code> from the
+ * specified provider.
+ *
+ * @param algorithm The name of the <code>CertPathBuilder</code> to create.
+ * @param provider The provider to use.
* @return The new instance.
- * @throws NoSuchAlgorithmException If no installed provider
- * implements the named algorithm.
- * @throws IllegalArgumentException If <i>provider</i> in
- * <tt>null</tt>.
+ * @throws NoSuchAlgorithmException If no installed provider implements the
+ * named algorithm.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static CertPathBuilder getInstance(String algorithm, Provider provider)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("null provider");
+ StringBuilder sb = new StringBuilder("CertPathBuilder for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new CertPathBuilder((CertPathBuilderSpi)
- Engine.getInstance(CERT_PATH_BUILDER, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(CERT_PATH_BUILDER, algorithm, provider);
+ return new CertPathBuilder((CertPathBuilderSpi) spi, provider, algorithm);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
/**
* Return the name of this CertPathBuilder algorithm.
*
diff --git a/java/security/cert/CertPathValidator.java b/java/security/cert/CertPathValidator.java
index 5fed19e9a..bf7c9746e 100644
--- a/java/security/cert/CertPathValidator.java
+++ b/java/security/cert/CertPathValidator.java
@@ -40,6 +40,7 @@ package java.security.cert;
import gnu.java.security.Engine;
+import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
@@ -124,91 +125,103 @@ public class CertPathValidator {
}
/**
- * Get an instance of the given validator from the first provider that
+ * Returns an instance of the given validator from the first provider that
* implements it.
- *
+ *
* @param algorithm The name of the algorithm to get.
* @return The new instance.
- * @throws NoSuchAlgorithmException If no installed provider
- * implements the requested algorithm.
+ * @throws NoSuchAlgorithmException If no installed provider implements the
+ * requested algorithm.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static CertPathValidator getInstance(String algorithm)
throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(algorithm, p[i]);
- }
- catch (NoSuchAlgorithmException e)
- {
- // Ignored.
- }
- }
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
/**
- * Get an instance of the given validator from the named provider.
- *
+ * Returns an instance of the given validator from the named provider.
+ *
* @param algorithm The name of the algorithm to get.
- * @param provider The name of the provider from which to get the
- * implementation.
+ * @param provider The name of the provider from which to get the
+ * implementation.
* @return The new instance.
- * @throws NoSuchAlgorithmException If the named provider does not
- * implement the algorithm.
- * @throws NoSuchProviderException If no provider named
- * <i>provider</i> is installed.
+ * @throws NoSuchAlgorithmException If the named provider does not implement
+ * the algorithm.
+ * @throws NoSuchProviderException If no provider named <i>provider</i> is
+ * installed.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
- public static CertPathValidator getInstance(String algorithm,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ public static CertPathValidator getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
/**
- * Get an instance of the given validator from the given provider.
- *
+ * Returns an instance of the given validator from the given provider.
+ *
* @param algorithm The name of the algorithm to get.
- * @param provider The provider from which to get the implementation.
+ * @param provider The provider from which to get the implementation.
* @return The new instance.
- * @throws NoSuchAlgorithmException If the provider does not implement
- * the algorithm.
- * @throws IllegalArgumentException If <i>provider</i> is null.
+ * @throws NoSuchAlgorithmException If the provider does not implement the
+ * algorithm.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static CertPathValidator getInstance(String algorithm,
Provider provider)
throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("null provider");
-
+ StringBuilder sb = new StringBuilder("CertPathValidator for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new CertPathValidator((CertPathValidatorSpi)
- Engine.getInstance(CERT_PATH_VALIDATOR, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(CERT_PATH_VALIDATOR, algorithm, provider);
+ return new CertPathValidator((CertPathValidatorSpi) spi, provider, algorithm);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
/**
* Return the name of this validator.
*
diff --git a/java/security/cert/CertStore.java b/java/security/cert/CertStore.java
index 864da868f..a2d1de335 100644
--- a/java/security/cert/CertStore.java
+++ b/java/security/cert/CertStore.java
@@ -40,6 +40,7 @@ package java.security.cert;
import gnu.java.security.Engine;
+import java.lang.reflect.InvocationTargetException;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
@@ -123,59 +124,63 @@ public class CertStore
}
/**
- * Get an instance of the given certificate store from the first
+ * Returns an instance of the given certificate store type from the first
* installed provider.
- *
- * @param type The type of CertStore to create.
- * @param params The parameters to initialize this cert store with.
+ *
+ * @param type The type of <code>CertStore</code> to create.
+ * @param params The parameters to initialize this cert store with.
* @return The new instance.
- * @throws InvalidAlgorithmParameterException If the instance rejects
- * the specified parameters.
- * @throws NoSuchAlgorithmException If no installed provider
- * implements the specified CertStore.
- * @throws IllegalArgumentException If <i>provider</i> is null.
+ * @throws InvalidAlgorithmParameterException If the instance rejects the
+ * specified parameters.
+ * @throws NoSuchAlgorithmException If no installed provider implements the
+ * specified CertStore.
+ * @throws IllegalArgumentException if <code>type</code> is
+ * <code>null</code> or is an empty string.
*/
public static CertStore getInstance(String type, CertStoreParameters params)
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(type, params, p[i]);
- }
- catch (NoSuchAlgorithmException e)
- {
- // Ignored.
- }
- }
-
+ try
+ {
+ return getInstance(type, params, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(type);
}
/**
- * Get an instance of the given certificate store from the named
+ * Returns an instance of the given certificate store type from a named
* provider.
- *
- * @param type The type of CertStore to create.
- * @param params The parameters to initialize this cert store with.
- * @param provider The name of the provider from which to get the
- * implementation.
+ *
+ * @param type The type of <code>CertStore</code> to create.
+ * @param params The parameters to initialize this cert store with.
+ * @param provider The name of the provider to use.
* @return The new instance.
- * @throws InvalidAlgorithmParameterException If the instance rejects
- * the specified parameters.
+ * @throws InvalidAlgorithmParameterException If the instance rejects the
+ * specified parameters.
* @throws NoSuchAlgorithmException If the specified provider does not
- * implement the specified CertStore.
- * @throws NoSuchProviderException If no provider named
- * <i>provider</i> is installed.
- * @throws IllegalArgumentException If <i>provider</i> is null.
+ * implement the specified CertStore.
+ * @throws NoSuchProviderException If no provider named <i>provider</i> is
+ * installed.
+ * @throws IllegalArgumentException if either <code>type</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>type</code> is an empty string.
*/
public static CertStore getInstance(String type, CertStoreParameters params,
String provider)
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException,
NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
@@ -183,48 +188,52 @@ public class CertStore
}
/**
- * Get an instance of the given certificate store from the given
+ * Returns an instance of the given certificate store type from a given
* provider.
*
- * @param type The type of CertStore to create.
+ * @param type The type of <code>CertStore</code> to create.
* @param params The parameters to initialize this cert store with.
- * @param provider The provider from which to get the implementation.
+ * @param provider The provider to use.
* @return The new instance.
* @throws InvalidAlgorithmParameterException If the instance rejects
* the specified parameters.
* @throws NoSuchAlgorithmException If the specified provider does not
* implement the specified CertStore.
- * @throws IllegalArgumentException If <i>provider</i> is null.
+ * @throws IllegalArgumentException if either <code>type</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>type</code> is an empty string.
*/
public static CertStore getInstance(String type, CertStoreParameters params,
Provider provider)
- throws InvalidAlgorithmParameterException, NoSuchAlgorithmException
+ throws InvalidAlgorithmParameterException, NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("null provider");
-
+ StringBuilder sb = new StringBuilder("CertStore of type [")
+ .append(type).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new CertStore((CertStoreSpi) Engine.getInstance(CERT_STORE,
- type, provider, new Object[] { params }), provider, type, params);
+ Object[] args = new Object[] { params };
+ Object spi = Engine.getInstance(CERT_STORE, type, provider, args);
+ return new CertStore((CertStoreSpi) spi, provider, type, params);
}
- catch (ClassCastException cce)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(type);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (ClassCastException x)
{
- Throwable cause = ite.getCause();
- if (cause instanceof InvalidAlgorithmParameterException)
- throw (InvalidAlgorithmParameterException) cause;
- else
- throw new NoSuchAlgorithmException(type);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
/**
* Return the type of certificate store this instance represents.
*
diff --git a/java/security/cert/CertificateFactory.java b/java/security/cert/CertificateFactory.java
index aedeff535..9a7db6cd5 100644
--- a/java/security/cert/CertificateFactory.java
+++ b/java/security/cert/CertificateFactory.java
@@ -41,6 +41,8 @@ package java.security.cert;
import gnu.java.security.Engine;
import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
@@ -84,106 +86,102 @@ public class CertificateFactory
this.type = type;
}
- // Class methods.
- // ------------------------------------------------------------------------
-
- /**
- * Gets an instance of the CertificateFactory class representing
- * the specified certificate factory. If the type is not
- * found then, it throws CertificateException.
- *
- * @param type The type of certificate factory to create.
- * @return a CertificateFactory repesenting the desired type
- * @throws CertificateException If the type of certificate is not
- * implemented by any installed provider.
+ /**
+ * Returns an instance of a <code>CertificateFactory</code> representing the
+ * specified certificate factory type.
+ *
+ * @param type The type of certificate factory to create.
+ * @return A <code>CertificateFactory</code> of the desired type.
+ * @throws CertificateException If the type of certificate factory is not
+ * implemented by any installed provider.
+ * @throws IllegalArgumentException if <code>type</code> is
+ * <code>null</code> or is an empty string.
*/
public static final CertificateFactory getInstance(String type)
- throws CertificateException
+ throws CertificateException
{
Provider[] p = Security.getProviders();
-
+ CertificateException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(type, p[i]);
- }
- catch (CertificateException e)
- {
- // Ignored.
- }
- }
-
+ try
+ {
+ return getInstance(type, p[i]);
+ }
+ catch (CertificateException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new CertificateException(type);
}
- /**
- * Gets an instance of the CertificateFactory class representing
- * the specified certificate factory from the specified provider.
- * If the type is not found then, it throws {@link CertificateException}.
- * If the provider is not found, then it throws
- * {@link java.security.NoSuchProviderException}.
- *
- * @param type The type of certificate factory to create.
- * @param provider The name of the provider from which to get the
- * implementation.
- * @return A CertificateFactory for the desired type.
- * @throws CertificateException If the type of certificate is not
- * implemented by the named provider.
+ /**
+ * Returns an instance of a <code>CertificateFactory</code> representing the
+ * specified certificate factory type from the named provider.
+ *
+ * @param type The type of certificate factory to create.
+ * @param provider The name of the provider to use.
+ * @return A <code>CertificateFactory</code> for the desired type.
+ * @throws CertificateException If the type of certificate is not implemented
+ * by the named provider.
* @throws NoSuchProviderException If the named provider is not installed.
+ * @throws IllegalArgumentException if either <code>type</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>type</code> is an empty string.
*/
public static final CertificateFactory getInstance(String type,
String provider)
throws CertificateException, NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
- if( p == null)
+ if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(type, p);
}
/**
- * Get a certificate factory for the given certificate type from the
- * given provider.
- *
- * @param type The type of certificate factory to create.
+ * Returns an instance of a <code>CertificateFactory</code> representing the
+ * specified certificate factory type from the designated provider.
+ *
+ * @param type The type of certificate factory to create.
* @param provider The provider from which to get the implementation.
- * @return A CertificateFactory for the desired type.
- * @throws CertificateException If the type of certificate is not
- * implemented by the provider.
- * @throws IllegalArgumentException If the provider is null.
+ * @return A <code>CertificateFactory</code> for the desired type.
+ * @throws CertificateException If the type of certificate is not implemented
+ * by the provider.
+ * @throws IllegalArgumentException if either <code>type</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>type</code> is an empty string.
*/
public static final CertificateFactory getInstance(String type,
Provider provider)
- throws CertificateException
+ throws CertificateException
{
- if (provider == null)
- throw new IllegalArgumentException("null provider");
-
+ Throwable cause;
try
{
- return new CertificateFactory((CertificateFactorySpi)
- Engine.getInstance(CERTIFICATE_FACTORY, type, provider),
- provider, type);
+ Object spi = Engine.getInstance(CERTIFICATE_FACTORY, type, provider);
+ return new CertificateFactory((CertificateFactorySpi) spi, provider, type);
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new CertificateException(type);
+ cause = x;
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new CertificateException(type);
+ cause = x.getCause() != null ? x.getCause() : x;
}
- catch (NoSuchAlgorithmException nsae)
+ catch (NoSuchAlgorithmException x)
{
- throw new CertificateException(nsae.getMessage());
+ cause = x;
}
+ CertificateException x = new CertificateException(type);
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
/**
* Gets the provider of this implementation.
*
diff --git a/java/text/SimpleDateFormat.java b/java/text/SimpleDateFormat.java
index 2825c7bed..1e1952569 100644
--- a/java/text/SimpleDateFormat.java
+++ b/java/text/SimpleDateFormat.java
@@ -917,7 +917,25 @@ public class SimpleDateFormat extends DateFormat
|| ((ch < 'a' || ch > 'z')
&& (ch < 'A' || ch > 'Z')))
{
- if (! expect (dateStr, pos, ch))
+ if (quote_start == -1 && ch == ' ')
+ {
+ // A single unquoted space in the pattern may match
+ // any number of spaces in the input.
+ int index = pos.getIndex();
+ int save = index;
+ while (index < dateStr.length()
+ && Character.isWhitespace(dateStr.charAt(index)))
+ ++index;
+ if (index > save)
+ pos.setIndex(index);
+ else
+ {
+ // Didn't see any whitespace.
+ pos.setErrorIndex(index);
+ return null;
+ }
+ }
+ else if (! expect (dateStr, pos, ch))
return null;
continue;
}
diff --git a/java/util/Arrays.java b/java/util/Arrays.java
index 10b31ee10..1fa595941 100644
--- a/java/util/Arrays.java
+++ b/java/util/Arrays.java
@@ -1,5 +1,5 @@
/* Arrays.java -- Utility class with methods to operate on arrays
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -2341,8 +2341,10 @@ public class Arrays
* value modification. The returned list implements both Serializable and
* RandomAccess.
*
- * @param a the array to return a view of
+ * @param a the array to return a view of (<code>null</code> not permitted)
* @return a fixed-size list, changes to which "write through" to the array
+ *
+ * @throws NullPointerException if <code>a</code> is <code>null</code>.
* @see Serializable
* @see RandomAccess
* @see Arrays.ArrayList
diff --git a/java/util/GregorianCalendar.java b/java/util/GregorianCalendar.java
index 5ce053a37..83ac00e77 100644
--- a/java/util/GregorianCalendar.java
+++ b/java/util/GregorianCalendar.java
@@ -445,7 +445,7 @@ public class GregorianCalendar extends Calendar
if (isSet[WEEK_OF_MONTH])
{
- int weeks = (month == 1 && leap == 0) ? 4 : 5;
+ int weeks = (month == 1 && leap == 0) ? 5 : 6;
if (fields[WEEK_OF_MONTH] < 1 || fields[WEEK_OF_MONTH] > weeks)
throw new IllegalArgumentException("Illegal WEEK_OF_MONTH.");
}
@@ -1164,7 +1164,7 @@ public class GregorianCalendar extends Calendar
*/
private static final int[] maximums =
{
- AD, 5000000, 11, 53, 5, 31, 366,
+ AD, 5000000, 11, 53, 6, 31, 366,
SATURDAY, 5, PM, 12, 23, 59, 59, 999,
+(12 * 60 * 60 * 1000),
(12 * 60 * 60 * 1000)
diff --git a/java/util/Locale.java b/java/util/Locale.java
index d2aead43c..001c7afde 100644
--- a/java/util/Locale.java
+++ b/java/util/Locale.java
@@ -188,11 +188,17 @@ public final class Locale implements Serializable, Cloneable
private String variant;
/**
- * This is the cached hashcode. When writing to stream, we write -1.
+ * This is where the JDK caches its hashcode. This is is only here
+ * for serialization purposes. The actual cache is hashcodeCache
*
* @serial should be -1 in serial streams
*/
- private transient int hashcode;
+ private int hashcode = -1;
+
+ /**
+ * This is the cached hashcode.
+ */
+ private transient int hashcodeCache;
/**
* Array storing all available locales.
@@ -324,7 +330,7 @@ public final class Locale implements Serializable, Cloneable
this.language = language;
this.country = country;
this.variant = variant;
- hashcode = language.hashCode() ^ country.hashCode() ^ variant.hashCode();
+ hashcodeCache = language.hashCode() ^ country.hashCode() ^ variant.hashCode();
}
/**
@@ -899,7 +905,7 @@ public final class Locale implements Serializable, Cloneable
*/
public int hashCode()
{
- return hashcode;
+ return hashcodeCache;
}
/**
@@ -917,32 +923,12 @@ public final class Locale implements Serializable, Cloneable
return false;
Locale l = (Locale) obj;
- return (language == l.language
- && country == l.country
+ return (language == l.language
+ && country == l.country
&& variant == l.variant);
}
/**
- * Write the locale to an object stream.
- *
- * @param s the stream to write to
- * @throws IOException if the write fails
- * @serialData The first three fields are Strings representing language,
- * country, and variant. The fourth field is a placeholder for
- * the cached hashcode, but this is always written as -1, and
- * recomputed when reading it back.
- */
- private void writeObject(ObjectOutputStream s)
- throws IOException
- {
- s.writeObject(language);
- s.writeObject(country);
- s.writeObject(variant);
- // Hashcode field is always written as -1.
- s.writeInt(-1);
- }
-
- /**
* Reads a locale from the input stream.
*
* @param s the stream to read from
@@ -953,10 +939,10 @@ public final class Locale implements Serializable, Cloneable
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
{
- language = ((String) s.readObject()).intern();
- country = ((String) s.readObject()).intern();
- variant = ((String) s.readObject()).intern();
- // Recompute hashcode.
- hashcode = language.hashCode() ^ country.hashCode() ^ variant.hashCode();
+ s.defaultReadObject();
+ language = language.intern();
+ country = country.intern();
+ variant = variant.intern();
+ hashcodeCache = language.hashCode() ^ country.hashCode() ^ variant.hashCode();
}
} // class Locale
diff --git a/java/util/ResourceBundle.java b/java/util/ResourceBundle.java
index 4dcb9ad16..0d2f104b9 100644
--- a/java/util/ResourceBundle.java
+++ b/java/util/ResourceBundle.java
@@ -91,6 +91,14 @@ baseName</pre>
public abstract class ResourceBundle
{
/**
+ * Maximum size of our cache of <code>ResourceBundle</code>s keyed by
+ * {@link BundleKey} instances.
+ *
+ * @see BundleKey
+ */
+ private static final int CACHE_SIZE = 100;
+
+ /**
* The parent bundle. This is consulted when you call getObject and there
* is no such resource in the current bundle. This field may be null.
*/
@@ -104,21 +112,22 @@ public abstract class ResourceBundle
private Locale locale;
/**
- * The resource bundle cache.
- */
- private static Map bundleCache;
-
- /**
- * The last default Locale we saw. If this ever changes then we have to
- * reset our caches.
- */
- private static Locale lastDefaultLocale;
-
- /**
- * The `empty' locale is created once in order to optimize
- * tryBundle().
+ * A VM-wide cache of resource bundles already fetched.
+ * <p>
+ * This {@link Map} is a Least Recently Used (LRU) cache, of the last
+ * {@link #CACHE_SIZE} accessed <code>ResourceBundle</code>s keyed by the
+ * tuple: default locale, resource-bundle name, resource-bundle locale, and
+ * classloader.
+ *
+ * @see BundleKey
*/
- private static final Locale emptyLocale = new Locale("");
+ private static Map bundleCache = new LinkedHashMap(CACHE_SIZE + 1, 0.75F, true)
+ {
+ public boolean removeEldestEntry(Map.Entry entry)
+ {
+ return size() > CACHE_SIZE;
+ }
+ };
/**
* The constructor. It does nothing special.
@@ -246,6 +255,7 @@ public abstract class ResourceBundle
by the combination of bundle name, locale, and class loader. */
private static class BundleKey
{
+ Locale defaultLocale;
String baseName;
Locale locale;
ClassLoader classLoader;
@@ -253,18 +263,19 @@ public abstract class ResourceBundle
BundleKey() {}
- BundleKey(String s, Locale l, ClassLoader cl)
+ BundleKey(Locale dl, String s, Locale l, ClassLoader cl)
{
- set(s, l, cl);
+ set(dl, s, l, cl);
}
- void set(String s, Locale l, ClassLoader cl)
+ void set(Locale dl, String s, Locale l, ClassLoader cl)
{
+ defaultLocale = dl;
baseName = s;
locale = l;
classLoader = cl;
- hashcode = baseName.hashCode() ^ locale.hashCode() ^
- classLoader.hashCode();
+ hashcode = defaultLocale.hashCode() ^ baseName.hashCode()
+ ^ locale.hashCode() ^ classLoader.hashCode();
}
public int hashCode()
@@ -277,10 +288,11 @@ public abstract class ResourceBundle
if (! (o instanceof BundleKey))
return false;
BundleKey key = (BundleKey) o;
- return hashcode == key.hashcode &&
- baseName.equals(key.baseName) &&
- locale.equals(key.locale) &&
- classLoader.equals(key.classLoader);
+ return hashcode == key.hashcode
+ && defaultLocale.equals(key.defaultLocale)
+ && baseName.equals(key.baseName)
+ && locale.equals(key.locale)
+ && classLoader.equals(key.classLoader);
}
}
@@ -370,61 +382,39 @@ public abstract class ResourceBundle
public static synchronized ResourceBundle getBundle
(String baseName, Locale locale, ClassLoader classLoader)
{
- // If the default locale changed since the last time we were called,
- // all cache entries are invalidated.
Locale defaultLocale = Locale.getDefault();
- if (defaultLocale != lastDefaultLocale)
- {
- bundleCache = new HashMap();
- lastDefaultLocale = defaultLocale;
- }
-
// This will throw NullPointerException if any arguments are null.
- lookupKey.set(baseName, locale, classLoader);
-
+ lookupKey.set(defaultLocale, baseName, locale, classLoader);
Object obj = bundleCache.get(lookupKey);
- ResourceBundle rb = null;
-
if (obj instanceof ResourceBundle)
+ return (ResourceBundle) obj;
+
+ if (obj == nullEntry)
+ throw new MissingResourceException("Bundle " + baseName
+ + " not found for locale " + locale
+ + " by classloader " + classLoader,
+ baseName, "");
+ // First, look for a bundle for the specified locale. We don't want
+ // the base bundle this time.
+ boolean wantBase = locale.equals(defaultLocale);
+ ResourceBundle bundle = tryBundle(baseName, locale, classLoader, wantBase);
+ // Try the default locale if neccessary.
+ if (bundle == null && ! wantBase)
+ bundle = tryBundle(baseName, defaultLocale, classLoader, true);
+
+ BundleKey key = new BundleKey(defaultLocale, baseName, locale, classLoader);
+ if (bundle == null)
{
- return (ResourceBundle) obj;
- }
- else if (obj == nullEntry)
- {
- // Lookup has failed previously. Fall through.
+ // Cache the fact that this lookup has previously failed.
+ bundleCache.put(key, nullEntry);
+ throw new MissingResourceException("Bundle " + baseName
+ + " not found for locale " + locale
+ + " by classloader " + classLoader,
+ baseName, "");
}
- else
- {
- // First, look for a bundle for the specified locale. We don't want
- // the base bundle this time.
- boolean wantBase = locale.equals(defaultLocale);
- ResourceBundle bundle = tryBundle(baseName, locale, classLoader,
- wantBase);
-
- // Try the default locale if neccessary.
- if (bundle == null && !locale.equals(defaultLocale))
- bundle = tryBundle(baseName, defaultLocale, classLoader, true);
-
- BundleKey key = new BundleKey(baseName, locale, classLoader);
- if (bundle == null)
- {
- // Cache the fact that this lookup has previously failed.
- bundleCache.put(key, nullEntry);
- }
- else
- {
- // Cache the result and return it.
- bundleCache.put(key, bundle);
- return bundle;
- }
- }
-
- throw new MissingResourceException("Bundle " + baseName
- + " not found for locale "
- + locale
- + " by classloader "
- + classLoader,
- baseName, "");
+ // Cache the result and return it.
+ bundleCache.put(key, bundle);
+ return bundle;
}
/**
diff --git a/java/util/UUID.java b/java/util/UUID.java
new file mode 100644
index 000000000..6a57d27b4
--- /dev/null
+++ b/java/util/UUID.java
@@ -0,0 +1,383 @@
+/* UUID.java -- Class that represents a UUID object.
+ 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.util;
+
+import java.io.Serializable;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * This class represents a 128-bit UUID value.
+ *
+ * There are several types of UUID, and while this class can be used to store
+ * them, only the Leach-Salz (variant 2) UUID specified in RFC-4122 will
+ * give meaningful results from the method calls.
+ * See: http://tools.ietf.org/html/4122 for the details
+ *
+ * The format of a Leach-Salz (variant 2) time-based (version 1) UUID
+ * is as follows:
+ * time_low - upper 32 bits of the most significant 64 bits,
+ * this is the least-significant part of the timestamp.
+ *
+ * time_mid - bits 16-31 of the most significant 64 bits,
+ * this is the middle portion of the timestamp.
+ *
+ * version - bits 8-15 of the most significant 64 bits.
+ *
+ * time_hi - bits 0-7 of the most significant 64 bits,
+ * the most significant portion of the timestamp.
+ *
+ * clock_and_reserved - bits 48-63 of the least significant 64 bits.
+ * a variable number of bits hold the variant
+ * (see the spec)
+ *
+ * node identifier - bits 0-47 of the least signficant 64 bits.
+ *
+ * These fields are valid only for version 1, in the remaining versions,
+ * only the version and variant fields are set, all others are used for data.
+ *
+ * @since 1.5
+ * @author Sven de Marothy
+ */
+public final class UUID
+ extends Object
+ implements Serializable, Comparable // genericizeme!
+{
+ private static final long serialVersionUID = -4856846361193249489L;
+
+ /**
+ * Serialized field - most significant 64 bits.
+ */
+ private long mostSigBits;
+
+ /**
+ * Serialized field - least significant 64 bits.
+ */
+ private long leastSigBits;
+
+ /**
+ * Random-number generator.
+ */
+ private static transient Random r = new Random();
+
+ /**
+ * Constructs a new UUID.
+ *
+ * @since 1.5
+ */
+ public UUID(long mostSigBits, long leastSigBits)
+ {
+ this.mostSigBits = mostSigBits;
+ this.leastSigBits = leastSigBits;
+ }
+
+ /**
+ * Returns the clock-sequence value of this UUID.
+ * This field only exists in a time-based (version 1) UUID.
+ *
+ * @throws UnsupportedOperationException if the UUID type is not 1.
+ * @returns an int containing the clock-sequence value.
+ */
+ public int clockSequence()
+ {
+ if( version() != 1 )
+ throw new UnsupportedOperationException("Not a type 1 UUID");
+ return (int)((leastSigBits & 0x3FFF000000000000L) >> 48);
+ }
+
+ /**
+ * Compare this UUID to another.
+ * The comparison is performed as between two 128-bit integers.
+ *
+ * @return -1 if this < val, 0 if they are equal, 1 if this > val.
+ */
+ public int compareTo(Object val)
+ {
+ return compareTo((UUID)val);
+ }
+
+ /**
+ * Compare this UUID to another.
+ * The comparison is performed as between two 128-bit integers.
+ *
+ * @return -1 if this < val, 0 if they are equal, 1 if this > val.
+ */
+ public int compareTo(UUID o)
+ {
+ if( mostSigBits < o.mostSigBits )
+ return -1;
+ if( mostSigBits > o.mostSigBits )
+ return 1;
+ if( leastSigBits < o.leastSigBits )
+ return -1;
+ if( leastSigBits > o.mostSigBits )
+ return 1;
+ return 0;
+ }
+
+ /**
+ * Compare a (UUID) object to this one
+ */
+ public boolean equals(Object obj)
+ {
+ if( !(obj instanceof UUID ) )
+ return false;
+ return ( ((UUID)obj).mostSigBits == mostSigBits &&
+ ((UUID)obj).leastSigBits == leastSigBits );
+ }
+
+ /**
+ * Creates a UUID object from a Sting representation.
+ *
+ * For the format of the string,
+ * @see #toString()
+ *
+ * @return a new UUID object.
+ */
+ public static UUID fromString(String name)
+ {
+ StringTokenizer st = new StringTokenizer( name.trim(), "-" );
+ if( st.countTokens() < 5 )
+ throw new IllegalArgumentException( "Incorrect UUID string"+
+ " representation:"+name );
+
+ long msb = (Long.parseLong(st.nextToken(), 16) << 32); // time low
+ msb |= (Long.parseLong(st.nextToken(), 16) << 16); // time mid
+ msb |= Long.parseLong(st.nextToken(), 16); // time high
+
+ long lsb = (Long.parseLong(st.nextToken(), 16) << 48); // clock
+ lsb |= Long.parseLong(st.nextToken(), 16); // node
+
+ return new UUID(msb, lsb);
+ }
+
+ /**
+ * Returns a String representation of the UUID.
+ *
+ * The format of the standard string representation (given in RFC4122) is:
+ *
+ * time-low "-" time-mid "-"
+ * time-high-and-version "-"
+ * clock-seq-and-reserved
+ * clock-seq-low "-" node
+ *
+ * Where each field is represented as a hex string.
+ *
+ * @return the String representation.
+ */
+ public String toString()
+ {
+ return // time-low first
+ padHex( (( mostSigBits & 0xFFFFFFFF00000000L) >> 32) & 0xFFFFFFFFL, 8)
+ + "-" + // then time-mid
+ padHex( (( mostSigBits & 0xFFFF0000L ) >> 16), 4 )
+ + "-" + // time-high
+ padHex( ( mostSigBits & 0x0000000000000000FFFFL ), 4 )
+ + "-" + // clock (note - no reason to separate high and low here)
+ padHex( (((leastSigBits & 0xFFFF000000000000L) >> 48) & 0xFFFF), 4 )
+ + "-" + // finally the node value.
+ padHex(leastSigBits & 0xFFFFFFFFFFFFL, 12);
+ }
+
+ /**
+ * Returns the least significant 64 bits of the UUID as a <code>long</code>.
+ */
+ public long getLeastSignificantBits()
+ {
+ return leastSigBits;
+ }
+
+ /**
+ * Returns the most significant 64 bits of the UUID as a <code>long</code>.
+ */
+ public long getMostSignificantBits()
+ {
+ return mostSigBits;
+ }
+
+ /**
+ * Returns a hash of this UUID.
+ */
+ public int hashCode()
+ {
+ int l1 = (int)(leastSigBits & 0xFFFFFFFFL);
+ int l2 = (int)((leastSigBits & 0xFFFFFFFF00000000L) >> 32);
+ int m1 = (int)(mostSigBits & 0xFFFFFFFFL);
+ int m2 = (int)((mostSigBits & 0xFFFFFFFF00000000L) >> 32);
+
+ return (l1 ^ l2) ^ (m1 ^ m2);
+ }
+
+ /**
+ * Creates a UUID version 3 object (name based with MD5 hashing)
+ * from a series of bytes representing a name.
+ */
+ public static UUID nameUUIDFromBytes(byte[] name)
+ {
+ long msb, lsb;
+ byte[] hash;
+
+ try
+ {
+ MessageDigest md5 = MessageDigest.getInstance("MD5");
+ hash = md5.digest( name );
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new UnsupportedOperationException("No MD5 algorithm available.");
+ }
+
+ msb = ((hash[0] & 0xFFL) << 56) | ((hash[1] & 0xFFL) << 48) |
+ ((hash[2] & 0xFFL) << 40) | ((hash[3] & 0xFFL) << 32) |
+ ((hash[4] & 0xFFL) << 24) | ((hash[5] & 0xFFL) << 16) |
+ ((hash[6] & 0xFFL) << 8) | (hash[7] & 0xFFL);
+
+ lsb = ((hash[8] & 0xFFL) << 56) | ((hash[9] & 0xFFL) << 48) |
+ ((hash[10] & 0xFFL) << 40) | ((hash[11] & 0xFFL) << 32) |
+ ((hash[12] & 0xFFL) << 24) | ((hash[13] & 0xFFL) << 16) |
+ ((hash[14] & 0xFFL) << 8) | (hash[15] & 0xFFL);
+
+ lsb &= 0x3FFFFFFFFFFFFFFFL;
+ lsb |= 0x8000000000000000L; // set top two bits to variant 2
+
+ msb &= 0xFFFFFFFFFFFF0FFFL;
+ msb |= 0x3000; // Version 3;
+
+ return new UUID(msb, lsb);
+ }
+
+ /**
+ * Returns the 48-bit node value in a long.
+ * This field only exists in a time-based (version 1) UUID.
+ *
+ * @throws UnsupportedOperationException if the UUID type is not 1.
+ * @returns a long with the node value in the lower 48 bits.
+ */
+ public long node()
+ {
+ if( version() != 1 )
+ throw new UnsupportedOperationException("Not a type 1 UUID");
+ return (leastSigBits & 0xFFFFFFFFFFFFL);
+ }
+
+ /**
+ * Returns the 60-bit timestamp value of the UUID in a long.
+ * This field only exists in a time-based (version 1) UUID.
+ *
+ * @throws UnsupportedOperationException if the UUID type is not 1.
+ * @returns a long with the timestamp value.
+ */
+ public long timestamp()
+ {
+ if( version() != 1 )
+ throw new UnsupportedOperationException("Not a type 1 UUID");
+ long time = (( mostSigBits & 0xFFFFFFFF00000000L) >> 32);
+ time |= (( mostSigBits & 0xFFFF0000L ) << 16);
+ long time_hi = ( mostSigBits & 0xFFFL );
+ time |= (time_hi << 48);
+ return time;
+ }
+
+ /**
+ * Generate a Leach-Salz (Variant 2) randomly generated (version 4)
+ * UUID.
+ *
+ */
+ public static UUID randomUUID()
+ {
+ long lsb = r.nextLong();
+ long msb = r.nextLong();
+
+ lsb &= 0x3FFFFFFFFFFFFFFFL;
+ lsb |= 0x8000000000000000L; // set top two bits to variant 2
+
+ msb &= 0xFFFFFFFFFFFF0FFFL;
+ msb |= 0x4000; // Version 4;
+
+ return new UUID( msb, lsb );
+ }
+
+ /**
+ * Returns a hex String from l, padded to n spaces.
+ */
+ private String padHex( long l, int n )
+ {
+ String s = Long.toHexString( l );
+ while( s.length() < n )
+ s = "0" + s;
+ return s;
+ }
+
+ /**
+ * Returns the variant of the UUID
+ *
+ * This may be:
+ * 0 = Reserved for NCS backwards-compatibility
+ * 2 = Leach-Salz (supports the other methods in this class)
+ * 6 = Reserved for Microsoft backwards-compatibility
+ * 7 = (reserved for future use)
+ */
+ public int variant()
+ {
+ // Get the top 3 bits (not all may be part of the variant)
+ int v = (int)((leastSigBits & 0xE000000000000000L) >> 61);
+ if( (v & 0x04) == 0 ) // msb of the variant is 0
+ return 0;
+ if( (v & 0x02) == 0 ) // variant is 0 1 (Leach-Salz)
+ return 2;
+ return v; // 6 or 7
+ }
+
+ /**
+ * Returns the version # of the UUID.
+ *
+ * Valid version numbers for a variant 2 UUID are:
+ * 1 = Time based UUID
+ * 2 = DCE security UUID
+ * 3 = Name-based UUID using MD5 hashing
+ * 4 = Randomly generated UUID
+ * 5 = Name-based UUID using SHA-1 hashing
+ *
+ * @return the version number
+ */
+ public int version()
+ {
+ return (int)((mostSigBits & 0xF000L) >> 12);
+ }
+}
diff --git a/java/util/Vector.java b/java/util/Vector.java
index 67549f0c4..eb72ae49d 100644
--- a/java/util/Vector.java
+++ b/java/util/Vector.java
@@ -1,5 +1,6 @@
/* Vector.java -- Class that provides growable arrays.
- Copyright (C) 1998, 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2004, 2005, 2006,
+ Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,6 +38,7 @@ exception statement from your version. */
package java.util;
+
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
@@ -479,7 +481,7 @@ public class Vector extends AbstractList
}
/**
- * Removes the first (the lowestindex) occurance of the given object from
+ * Removes the first (the lowest index) occurrence of the given object from
* the Vector. If such a remove was performed (the object was found), true
* is returned. If there was no such object, false is returned.
*
diff --git a/java/util/regex/Pattern.java b/java/util/regex/Pattern.java
index 89e67f9b4..d716fa4e6 100644
--- a/java/util/regex/Pattern.java
+++ b/java/util/regex/Pattern.java
@@ -73,12 +73,17 @@ public final class Pattern implements Serializable
this.regex = regex;
this.flags = flags;
+ RESyntax syntax = RESyntax.RE_SYNTAX_JAVA_1_4;
int gnuFlags = 0;
gnuFlags |= RE.REG_ICASE_USASCII;
if ((flags & CASE_INSENSITIVE) != 0)
gnuFlags |= RE.REG_ICASE;
if ((flags & MULTILINE) != 0)
- gnuFlags |= RE.REG_MULTILINE;
+ {
+ gnuFlags |= RE.REG_MULTILINE;
+ syntax = new RESyntax(syntax);
+ syntax.setLineSeparator(null);
+ }
if ((flags & DOTALL) != 0)
gnuFlags |= RE.REG_DOT_NEWLINE;
if ((flags & UNICODE_CASE) != 0)
@@ -86,7 +91,6 @@ public final class Pattern implements Serializable
// not yet supported:
// if ((flags & CANON_EQ) != 0) gnuFlags =
- RESyntax syntax = RESyntax.RE_SYNTAX_JAVA_1_4;
if ((flags & UNIX_LINES) != 0)
{
// Use a syntax set with \n for linefeeds?
diff --git a/java/util/zip/ZipFile.java b/java/util/zip/ZipFile.java
index 649e80d43..47ced0fb8 100644
--- a/java/util/zip/ZipFile.java
+++ b/java/util/zip/ZipFile.java
@@ -445,6 +445,7 @@ public class ZipFile implements ZipConstants
case ZipOutputStream.STORED:
return inp;
case ZipOutputStream.DEFLATED:
+ inp.addDummyByte();
final Inflater inf = new Inflater(true);
final int sz = (int) entry.getSize();
return new InflaterInputStream(inp, inf)
@@ -520,6 +521,11 @@ public class ZipFile implements ZipConstants
private long bufferOffset;
private int pos;
private long end;
+ // We may need to supply an extra dummy byte to our reader.
+ // See Inflater. We use a count here to simplify the logic
+ // elsewhere in this class. Note that we ignore the dummy
+ // byte in methods where we know it is not needed.
+ private int dummyByteCount;
public PartialInputStream(RandomAccessFile raf, int bufferSize)
throws IOException
@@ -540,8 +546,17 @@ public class ZipFile implements ZipConstants
{
synchronized (raf)
{
- raf.seek(bufferOffset);
- raf.readFully(buffer, 0, (int) Math.min(buffer.length, end - bufferOffset));
+ long len = end - bufferOffset;
+ if (len == 0 && dummyByteCount > 0)
+ {
+ buffer[0] = 0;
+ dummyByteCount = 0;
+ }
+ else
+ {
+ raf.seek(bufferOffset);
+ raf.readFully(buffer, 0, (int) Math.min(buffer.length, len));
+ }
}
}
@@ -555,7 +570,7 @@ public class ZipFile implements ZipConstants
public int read() throws IOException
{
- if (bufferOffset + pos >= end)
+ if (bufferOffset + pos >= end + dummyByteCount)
return -1;
if (pos == buffer.length)
{
@@ -569,9 +584,9 @@ public class ZipFile implements ZipConstants
public int read(byte[] b, int off, int len) throws IOException
{
- if (len > end - (bufferOffset + pos))
+ if (len > end + dummyByteCount - (bufferOffset + pos))
{
- len = (int) (end - (bufferOffset + pos));
+ len = (int) (end + dummyByteCount - (bufferOffset + pos));
if (len == 0)
return -1;
}
@@ -681,5 +696,10 @@ public class ZipFile implements ZipConstants
throw new AssertionError(uee);
}
}
+
+ public void addDummyByte()
+ {
+ dummyByteCount = 1;
+ }
}
}
diff --git a/javax/crypto/Cipher.java b/javax/crypto/Cipher.java
index 1f68ea605..7c18e6f6a 100644
--- a/javax/crypto/Cipher.java
+++ b/javax/crypto/Cipher.java
@@ -157,161 +157,159 @@ public class Cipher
/** Our current state (encrypting, wrapping, etc.) */
private int state;
-
- // Class methods.
- // ------------------------------------------------------------------------
-
/**
- * <p>Creates a new cipher instance for the given transformation.</p>
- *
- * <p>The installed providers are tried in order for an
- * implementation, and the first appropriate instance is returned. If
- * no installed provider can provide the implementation, an
- * appropriate exception is thrown.</p>
- *
+ * Creates a new cipher instance for the given transformation.
+ * <p>
+ * The installed providers are tried in order for an implementation, and the
+ * first appropriate instance is returned. If no installed provider can
+ * provide the implementation, an appropriate exception is thrown.
+ *
* @param transformation The transformation to create.
* @return An appropriate cipher for this transformation.
- * @throws java.security.NoSuchAlgorithmException If no installed
- * provider can supply the appropriate cipher or mode.
- * @throws javax.crypto.NoSuchPaddingException If no installed
- * provider can supply the appropriate padding.
+ * @throws NoSuchAlgorithmException If no installed provider can supply the
+ * appropriate cipher or mode.
+ * @throws NoSuchPaddingException If no installed provider can supply the
+ * appropriate padding.
*/
public static final Cipher getInstance(String transformation)
- throws NoSuchAlgorithmException, NoSuchPaddingException
+ throws NoSuchAlgorithmException, NoSuchPaddingException
{
- Provider[] providers = Security.getProviders();
- NoSuchPaddingException ex = null;
- String msg = "";
- for (int i = 0; i < providers.length; i++)
- {
- try
- {
- return getInstance(transformation, providers[i]);
- }
- catch (NoSuchAlgorithmException nsae)
- {
- msg = nsae.getMessage();
- ex = null;
- }
- catch (NoSuchPaddingException nspe)
- {
- ex = nspe;
- }
- }
- if (ex != null)
- {
- throw ex;
- }
- throw new NoSuchAlgorithmException(msg);
+ Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
+ NoSuchPaddingException lastPaddingException = null;
+ for (int i = 0; i < p.length; i++)
+ try
+ {
+ return getInstance(transformation, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ lastPaddingException = null;
+ }
+ catch (NoSuchPaddingException x)
+ {
+ lastPaddingException = x;
+ }
+ if (lastPaddingException != null)
+ throw lastPaddingException;
+ if (lastException != null)
+ throw lastException;
+ throw new NoSuchAlgorithmException(transformation);
}
/**
- * <p>Creates a new cipher instance for the given transformation and
- * the named provider.</p>
- *
+ * Creates a new cipher instance for the given transformation and the named
+ * provider.
+ *
* @param transformation The transformation to create.
- * @param provider The name of the provider to use.
+ * @param provider The name of the provider to use.
* @return An appropriate cipher for this transformation.
- * @throws java.security.NoSuchAlgorithmException If the provider cannot
- * supply the appropriate cipher or mode.
- * @throws java.security.NoSuchProviderException If the named provider
- * is not installed.
- * @throws javax.crypto.NoSuchPaddingException If the provider cannot
- * supply the appropriate padding.
+ * @throws NoSuchAlgorithmException If the provider cannot supply the
+ * appropriate cipher or mode.
+ * @throws NoSuchProviderException If the named provider is not installed.
+ * @throws NoSuchPaddingException If the provider cannot supply the
+ * appropriate padding.
+ * @throws IllegalArgumentException if either <code>transformation</code> or
+ * <code>provider</code> is <code>null</code>.
*/
public static final Cipher getInstance(String transformation, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException,
- NoSuchPaddingException
+ throws NoSuchAlgorithmException, NoSuchProviderException,
+ NoSuchPaddingException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
- {
- throw new NoSuchProviderException(provider);
- }
+ throw new NoSuchProviderException(provider);
return getInstance(transformation, p);
}
/**
- * Creates a new cipher instance for the given transform and the given
+ * Creates a new cipher instance for a given transformation from a given
* provider.
- *
+ *
* @param transformation The transformation to create.
- * @param provider The provider to use.
+ * @param provider The provider to use.
* @return An appropriate cipher for this transformation.
- * @throws java.security.NoSuchAlgorithmException If the given
- * provider cannot supply the appropriate cipher or mode.
- * @throws javax.crypto.NoSuchPaddingException If the given
- * provider cannot supply the appropriate padding scheme.
+ * @throws NoSuchAlgorithmException If the given provider cannot supply the
+ * appropriate cipher or mode.
+ * @throws NoSuchPaddingException If the given provider cannot supply the
+ * appropriate padding scheme.
*/
- public static final Cipher getInstance(String transformation, Provider provider)
- throws NoSuchAlgorithmException, NoSuchPaddingException
+ public static final Cipher getInstance(String transformation,
+ Provider provider)
+ throws NoSuchAlgorithmException, NoSuchPaddingException
{
- CipherSpi result = null;
- String key = null;
- String alg = null, mode = null, pad = null;
- String msg = "";
+ StringBuilder sb = new StringBuilder().append("Cipher transformation [")
+ .append(transformation).append("] from provider [")
+ .append(provider).append("] ");
+ Throwable cause;
+ Object spi;
+ CipherSpi result;
if (transformation.indexOf('/') < 0)
{
try
{
- result = (CipherSpi) Engine.getInstance(SERVICE, transformation,
- provider);
- return new Cipher(result, provider, transformation);
+ spi = Engine.getInstance(SERVICE, transformation, provider);
+ return new Cipher((CipherSpi) spi, provider, transformation);
}
catch (Exception e)
{
- msg = e.getMessage();
+ if (e instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) e;
+ cause = e;
}
}
else
{
StringTokenizer tok = new StringTokenizer(transformation, "/");
if (tok.countTokens() != 3)
- {
- throw new NoSuchAlgorithmException("badly formed transformation");
- }
- alg = tok.nextToken();
- mode = tok.nextToken();
- pad = tok.nextToken();
+ throw new NoSuchAlgorithmException(sb.append("is malformed").toString());
+
+ String alg = tok.nextToken();
+ String mode = tok.nextToken();
+ String pad = tok.nextToken();
try
{
- result = (CipherSpi) Engine.getInstance(SERVICE, transformation,
- provider);
- return new Cipher(result, provider, transformation);
+ spi = Engine.getInstance(SERVICE, transformation, provider);
+ return new Cipher((CipherSpi) spi, provider, transformation);
}
catch (Exception e)
{
- msg = e.getMessage();
+ cause = e;
}
+
try
{
- result = (CipherSpi) Engine.getInstance(SERVICE, alg + '/' + mode,
- provider);
+ spi = Engine.getInstance(SERVICE, alg + '/' + mode, provider);
+ result = (CipherSpi) spi;
result.engineSetPadding(pad);
return new Cipher(result, provider, transformation);
}
catch (Exception e)
{
if (e instanceof NoSuchPaddingException)
- {
- throw (NoSuchPaddingException) e;
- }
- msg = e.getMessage();
+ throw (NoSuchPaddingException) e;
+ cause = e;
}
+
try
{
- result = (CipherSpi) Engine.getInstance(SERVICE, alg + "//" + pad,
- provider);
+ spi = Engine.getInstance(SERVICE, alg + "//" + pad, provider);
+ result = (CipherSpi) spi;
result.engineSetMode(mode);
return new Cipher(result, provider, transformation);
}
catch (Exception e)
{
- msg = e.getMessage();
+ cause = e;
}
+
try
{
- result = (CipherSpi) Engine.getInstance(SERVICE, alg, provider);
+ spi = Engine.getInstance(SERVICE, alg, provider);
+ result = (CipherSpi) spi;
result.engineSetMode(mode);
result.engineSetPadding(pad);
return new Cipher(result, provider, transformation);
@@ -319,18 +317,16 @@ public class Cipher
catch (Exception e)
{
if (e instanceof NoSuchPaddingException)
- {
- throw (NoSuchPaddingException) e;
- }
- msg = e.getMessage();
+ throw (NoSuchPaddingException) e;
+ cause = e;
}
}
- throw new NoSuchAlgorithmException(transformation + ": " + msg);
+ sb.append("could not be created");
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Constructor.
- // ------------------------------------------------------------------------
-
/**
* Create a cipher.
*
@@ -347,9 +343,6 @@ public class Cipher
state = INITIAL_STATE;
}
- // Public instance methods.
- // ------------------------------------------------------------------------
-
/**
* Get the name that this cipher instance was created with; this is
* equivalent to the "transformation" argument given to any of the
@@ -639,13 +632,7 @@ public class Cipher
public final int getOutputSize(int inputLength) throws IllegalStateException
{
if (cipherSpi == null)
- {
- return inputLength;
- }
- if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
- {
- throw new IllegalStateException("neither encrypting nor decrypting");
- }
+ return inputLength;
return cipherSpi.engineGetOutputSize(inputLength);
}
diff --git a/javax/crypto/ExemptionMechanism.java b/javax/crypto/ExemptionMechanism.java
index b6cb02c63..baf6bad99 100644
--- a/javax/crypto/ExemptionMechanism.java
+++ b/javax/crypto/ExemptionMechanism.java
@@ -87,66 +87,111 @@ public class ExemptionMechanism
virgin = true;
}
- // Class methods.
- // ------------------------------------------------------------------------
-
+ /**
+ * Create an instance of <code>ExemptionMechanism</code> for a designated
+ * <code>mechanism</code> from the first Security Provider offering it.
+ *
+ * @param mechanism the name of the exemption mechanism to create.
+ * @return a newly created instance of <code>ExemptionMechanism</code>.
+ * @throws IllegalArgumentException if the provider is null.
+ * @throws NoSuchAlgorithmException if no such exemption mechanism is
+ * available from any known Security Provider.
+ * @throws IllegalArgumentException if <code>mechanism</code> is
+ * <code>null</code> or is an empty string.
+ */
public static final ExemptionMechanism getInstance(String mechanism)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- Provider[] provs = Security.getProviders();
- String msg = "";
- for (int i = 0; i < provs.length; i++)
- {
- try
- {
- return getInstance(mechanism, provs[i]);
- }
- catch (NoSuchAlgorithmException nsae)
- {
- msg = nsae.getMessage();
- }
- }
- throw new NoSuchAlgorithmException(msg);
+ Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
+ for (int i = 0; i < p.length; i++)
+ try
+ {
+ return getInstance(mechanism, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
+ throw new NoSuchAlgorithmException(mechanism);
}
+ /**
+ * Create an instance of <code>ExemptionMechanism</code> for a designated
+ * <code>mechanism</code> from a named <code>provider</code>.
+ *
+ * @param mechanism the name of the exemption mechanism to create.
+ * @param provider the security provider to provide the exemption
+ * <code>mechanism</code>.
+ * @return a newly created instance of <code>ExemptionMechanism</code>.
+ * @throws NoSuchAlgorithmException if no such exemption mechanism is
+ * available from the named <code>provider</code>.
+ * @throws NoSuchProviderException if no Security Provider with the designated
+ * name is known to the underlying JVM.
+ * @throws IllegalArgumentException if either <code>mechanism</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>mechanism</code> is an empty string.
+ */
public static final ExemptionMechanism getInstance(String mechanism,
String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
- {
- throw new NoSuchProviderException(provider);
- }
+ throw new NoSuchProviderException(provider);
return getInstance(mechanism, p);
}
+ /**
+ * Create an instance of <code>ExemptionMechanism</code> for a designated
+ * <code>mechanism</code> from a designated <code>provider</code>.
+ *
+ * @param mechanism the name of the exemption mechanism to create.
+ * @param provider the security provider to provide the exemption
+ * <code>mechanism</code>.
+ * @return a newly created instance of <code>ExemptionMechanism</code>.
+ * @throws NoSuchAlgorithmException if an exemption mechanism could not be
+ * created.
+ * @throws IllegalArgumentException if either <code>mechanism</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>mechanism</code> is an empty string.
+ */
public static final ExemptionMechanism getInstance(String mechanism,
Provider provider)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
+ StringBuilder sb = new StringBuilder("ExemptionMechanism [")
+ .append(mechanism).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new ExemptionMechanism((ExemptionMechanismSpi)
- Engine.getInstance(SERVICE, mechanism, provider),
- provider, mechanism);
+ Object spi = Engine.getInstance(SERVICE, mechanism, provider);
+ return new ExemptionMechanism((ExemptionMechanismSpi) spi,
+ provider,
+ mechanism);
}
- catch (InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- if (ite.getCause() instanceof NoSuchAlgorithmException)
- throw (NoSuchAlgorithmException) ite.getCause();
- else
- throw new NoSuchAlgorithmException(mechanism);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(mechanism);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
public final byte[] genExemptionBlob()
throws IllegalStateException, ExemptionMechanismException
{
diff --git a/javax/crypto/KeyAgreement.java b/javax/crypto/KeyAgreement.java
index d71743e3e..490031091 100644
--- a/javax/crypto/KeyAgreement.java
+++ b/javax/crypto/KeyAgreement.java
@@ -101,97 +101,103 @@ public class KeyAgreement
virgin = true;
}
- // Class methods.
- // ------------------------------------------------------------------------
-
/**
* Get an implementation of an algorithm from the first provider that
* implements it.
- *
+ *
* @param algorithm The name of the algorithm to get.
* @return The proper KeyAgreement instacne, if found.
- * @throws java.security.NoSuchAlgorithmException If the specified
- * algorithm is not implemented by any installed provider.
+ * @throws NoSuchAlgorithmException If the specified algorithm is not
+ * implemented by any installed provider.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static final KeyAgreement getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- Provider[] provs = Security.getProviders();
- String msg = algorithm;
- for (int i = 0; i < provs.length; i++)
- {
- try
- {
- return getInstance(algorithm, provs[i]);
- }
- catch (NoSuchAlgorithmException nsae)
- {
- msg = nsae.getMessage();
- }
- }
- throw new NoSuchAlgorithmException(msg);
+ Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
+ for (int i = 0; i < p.length; i++)
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
+ throw new NoSuchAlgorithmException(algorithm);
}
/**
- * Get an implementation of an algorithm from a named provider.
- *
- * @param algorithm The name of the algorithm to get.
- * @param provider The name of the provider from which to get the
- * implementation.
+ * Return an implementation of an algorithm from a named provider.
+ *
+ * @param algorithm The name of the algorithm to create.
+ * @param provider The name of the provider from which to get the
+ * implementation.
* @return The proper KeyAgreement instance, if found.
- * @throws java.security.NoSuchAlgorithmException If the named provider
- * does not implement the algorithm.
- * @throws java.security.NoSuchProviderException If the named provider
- * does not exist.
+ * @throws NoSuchAlgorithmException If the named provider does not implement
+ * the algorithm.
+ * @throws NoSuchProviderException If the named provider does not exist.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
- public static final KeyAgreement getInstance(String algorithm,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ public static final KeyAgreement getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
- {
- throw new NoSuchProviderException(provider);
- }
+ throw new NoSuchProviderException(provider);
return getInstance(algorithm, p);
}
/**
- * Get an implementation of an algorithm from a specific provider.
- *
+ * Return an implementation of an algorithm from a specific provider.
+ *
* @param algorithm The name of the algorithm to get.
- * @param provider The provider from which to get the implementation.
+ * @param provider The provider from which to get the implementation.
* @return The proper KeyAgreement instance, if found.
- * @throws java.security.NoSuchAlgorithmException If this provider
- * does not implement the algorithm.
+ * @throws NoSuchAlgorithmException If this provider does not implement the
+ * algorithm.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static final KeyAgreement getInstance(String algorithm,
Provider provider)
throws NoSuchAlgorithmException
{
+ StringBuilder sb = new StringBuilder("KeyAgreement algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new KeyAgreement((KeyAgreementSpi)
- Engine.getInstance(SERVICE, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(SERVICE, algorithm, provider);
+ return new KeyAgreement((KeyAgreementSpi) spi, provider, algorithm);
}
- catch (InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- if (ite.getCause() == null)
- throw new NoSuchAlgorithmException(algorithm);
- if (ite.getCause() instanceof NoSuchAlgorithmException)
- throw (NoSuchAlgorithmException) ite.getCause();
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
/**
* Do a phase in the key agreement. The number of times this method is
* called depends upon the algorithm and the number of parties
diff --git a/javax/crypto/KeyGenerator.java b/javax/crypto/KeyGenerator.java
index e824c6452..79334e9e0 100644
--- a/javax/crypto/KeyGenerator.java
+++ b/javax/crypto/KeyGenerator.java
@@ -94,95 +94,103 @@ public class KeyGenerator
this.algorithm = algorithm;
}
- // Class methods.
- // ------------------------------------------------------------------------
-
/**
- * Create a new key generator, returning the first available
- * implementation.
- *
+ * Create a new key generator, returning the first available implementation.
+ *
* @param algorithm The generator algorithm name.
- * @throws java.security.NoSuchAlgorithmException If the specified
- * algorithm does not exist.
+ * @throws NoSuchAlgorithmException If the specified algorithm does not exist.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static final KeyGenerator getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- Provider[] provs = Security.getProviders();
- String msg = algorithm;
- for (int i = 0; i < provs.length; i++)
- {
- try
- {
- return getInstance(algorithm, provs[i]);
- }
- catch (NoSuchAlgorithmException nsae)
- {
- msg = nsae.getMessage();
- }
- }
- throw new NoSuchAlgorithmException(msg);
+ Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
+ for (int i = 0; i < p.length; i++)
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
+ throw new NoSuchAlgorithmException(algorithm);
}
/**
* Create a new key generator from the named provider.
- *
+ *
* @param algorithm The generator algorithm name.
- * @param provider The name of the provider to use.
+ * @param provider The name of the provider to use.
* @return An appropriate key generator, if found.
- * @throws java.security.NoSuchAlgorithmException If the specified
- * algorithm is not implemented by the named provider.
- * @throws java.security.NoSuchProviderException If the named provider
- * does not exist.
+ * @throws NoSuchAlgorithmException If the specified algorithm is not
+ * implemented by the named provider.
+ * @throws NoSuchProviderException If the named provider does not exist.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static final KeyGenerator getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
- {
- throw new NoSuchProviderException(provider);
- }
+ throw new NoSuchProviderException(provider);
return getInstance(algorithm, p);
}
/**
* Create a new key generator from the supplied provider.
- *
+ *
* @param algorithm The generator algorithm name.
- * @param provider The provider to use.
+ * @param provider The provider to use.
* @return An appropriate key generator, if found.
- * @throws java.security.NoSuchAlgorithmException If the specified
- * algorithm is not implemented by the provider.
+ * @throws NoSuchAlgorithmException If the specified algorithm is not
+ * implemented by the provider.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
- public static final KeyGenerator getInstance(String algorithm, Provider provider)
- throws NoSuchAlgorithmException
+ public static final KeyGenerator getInstance(String algorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException
{
+ StringBuilder sb = new StringBuilder("KeyGenerator algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- KeyGenerator instance = new KeyGenerator((KeyGeneratorSpi)
- Engine.getInstance(SERVICE, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(SERVICE, algorithm, provider);
+ KeyGenerator instance = new KeyGenerator((KeyGeneratorSpi) spi,
+ provider,
+ algorithm);
instance.init(new SecureRandom());
return instance;
}
- catch (InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- if (ite.getCause() == null)
- throw new NoSuchAlgorithmException(algorithm);
- if (ite.getCause() instanceof NoSuchAlgorithmException)
- throw (NoSuchAlgorithmException) ite.getCause();
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
/**
* Generate a key.
*
diff --git a/javax/crypto/Mac.java b/javax/crypto/Mac.java
index abbff8b23..ea3e42ba6 100644
--- a/javax/crypto/Mac.java
+++ b/javax/crypto/Mac.java
@@ -107,96 +107,104 @@ public class Mac implements Cloneable
virgin = true;
}
- // Class methods.
- // ------------------------------------------------------------------------
-
/**
- * Get an instance of the named algorithm from the first provider with
- * an appropriate implementation.
- *
+ * Create an instance of the named algorithm from the first provider with an
+ * appropriate implementation.
+ *
* @param algorithm The name of the algorithm.
- * @return An appropriate Mac instance, if the specified algorithm
- * is implemented by a provider.
- * @throws java.security.NoSuchAlgorithmException If no implementation
- * of the named algorithm is installed.
+ * @return An appropriate Mac instance, if the specified algorithm is
+ * implemented by a provider.
+ * @throws NoSuchAlgorithmException If no implementation of the named
+ * algorithm is installed.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static final Mac getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- Provider[] provs = Security.getProviders();
- String msg = "";
- for (int i = 0; i < provs.length; i++)
- {
- try
- {
- return getInstance(algorithm, provs[i]);
- }
- catch (NoSuchAlgorithmException nsae)
- {
- msg = nsae.getMessage();
- }
- }
- throw new NoSuchAlgorithmException(msg);
+ Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
+ for (int i = 0; i < p.length; i++)
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
+ throw new NoSuchAlgorithmException(algorithm);
}
/**
- * Get an instance of the named algorithm from the named provider.
- *
+ * Create an instance of the named algorithm from the named provider.
+ *
* @param algorithm The name of the algorithm.
- * @param provider The name of the provider.
+ * @param provider The name of the provider.
* @return An appropriate Mac instance, if the specified algorithm is
* implemented by the named provider.
- * @throws java.security.NoSuchAlgorithmException If the named provider
- * has no implementation of the algorithm.
- * @throws java.security.NoSuchProviderException If the named provider
- * does not exist.
+ * @throws NoSuchAlgorithmException If the named provider has no
+ * implementation of the algorithm.
+ * @throws NoSuchProviderException If the named provider does not exist.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static final Mac getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
- {
- throw new NoSuchProviderException(provider);
- }
+ throw new NoSuchProviderException(provider);
return getInstance(algorithm, p);
}
/**
- * Get an instance of the named algorithm from a provider.
- *
+ * Create an instance of the named algorithm from a provider.
+ *
* @param algorithm The name of the algorithm.
- * @param provider The provider.
+ * @param provider The provider.
* @return An appropriate Mac instance, if the specified algorithm is
* implemented by the provider.
- * @throws java.security.NoSuchAlgorithmException If the provider
- * has no implementation of the algorithm.
+ * @throws NoSuchAlgorithmException If the provider has no implementation of
+ * the algorithm.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static final Mac getInstance(String algorithm, Provider provider)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
+ StringBuilder sb = new StringBuilder("Mac algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new Mac((MacSpi) Engine.getInstance(SERVICE, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(SERVICE, algorithm, provider);
+ return new Mac((MacSpi) spi, provider, algorithm);
}
- catch (InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- if (ite.getCause() == null)
- throw new NoSuchAlgorithmException(algorithm);
- if (ite.getCause() instanceof NoSuchAlgorithmException)
- throw (NoSuchAlgorithmException) ite.getCause();
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
/**
* Finishes the computation of a MAC and returns the digest.
*
diff --git a/javax/crypto/SecretKeyFactory.java b/javax/crypto/SecretKeyFactory.java
index 0a63ef067..1c857d274 100644
--- a/javax/crypto/SecretKeyFactory.java
+++ b/javax/crypto/SecretKeyFactory.java
@@ -94,94 +94,102 @@ public class SecretKeyFactory
this.algorithm = algorithm;
}
- // Class methods.
- // ------------------------------------------------------------------------
-
/**
- * Create a new secret key factory from the first appropriate
- * instance.
- *
+ * Create a new secret key factory from the first appropriate instance.
+ *
* @param algorithm The algorithm name.
* @return The appropriate key factory, if found.
- * @throws java.security.NoSuchAlgorithmException If no provider
- * implements the specified algorithm.
+ * @throws NoSuchAlgorithmException If no provider implements the specified
+ * algorithm.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static final SecretKeyFactory getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- Provider[] provs = Security.getProviders();
- for (int i = 0; i < provs.length; i++)
- {
- try
- {
- return getInstance(algorithm, provs[i]);
- }
- catch (NoSuchAlgorithmException nsae)
- {
- }
- }
- throw new NoSuchAlgorithmException(algorithm);
+ Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
+ for (int i = 0; i < p.length; i++)
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
+ throw new NoSuchAlgorithmException(algorithm);
}
/**
* Create a new secret key factory from the named provider.
- *
+ *
* @param algorithm The algorithm name.
- * @param provider The provider name.
+ * @param provider The provider name.
* @return The appropriate key factory, if found.
- * @throws java.security.NoSuchAlgorithmException If the named
- * provider does not implement the algorithm.
- * @throws java.security.NoSuchProviderException If the named provider
- * does not exist.
+ * @throws NoSuchAlgorithmException If the named provider does not implement
+ * the algorithm.
+ * @throws NoSuchProviderException If the named provider does not exist.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static final SecretKeyFactory getInstance(String algorithm,
String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
- {
- throw new NoSuchProviderException(provider);
- }
+ throw new NoSuchProviderException(provider);
return getInstance(algorithm, p);
}
/**
* Create a new secret key factory from the specified provider.
- *
+ *
* @param algorithm The algorithm name.
- * @param provider The provider.
+ * @param provider The provider.
* @return The appropriate key factory, if found.
- * @throws java.security.NoSuchAlgorithmException If the provider
- * does not implement the algorithm.
+ * @throws NoSuchAlgorithmException If the provider does not implement the
+ * algorithm.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static final SecretKeyFactory getInstance(String algorithm,
Provider provider)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
+ StringBuilder sb = new StringBuilder("SecretKeyFactory algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new SecretKeyFactory((SecretKeyFactorySpi)
- Engine.getInstance(SERVICE, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(SERVICE, algorithm, provider);
+ return new SecretKeyFactory((SecretKeyFactorySpi) spi, provider, algorithm);
}
- catch (InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- if (ite.getCause() == null)
- throw new NoSuchAlgorithmException(algorithm);
- if (ite.getCause() instanceof NoSuchAlgorithmException)
- throw (NoSuchAlgorithmException) ite.getCause();
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
/**
* Generate a secret key from a key specification, if possible.
*
diff --git a/javax/crypto/spec/SecretKeySpec.java b/javax/crypto/spec/SecretKeySpec.java
index 4caf51a46..86c4e05d4 100644
--- a/javax/crypto/spec/SecretKeySpec.java
+++ b/javax/crypto/spec/SecretKeySpec.java
@@ -133,14 +133,22 @@ public class SecretKeySpec implements KeySpec, SecretKey
public boolean equals(Object o)
{
- byte[] okey = ((SecretKeySpec) o).getEncoded();
- if (key.length != okey.length) return false;
- for (int i = 0; i < key.length; i++)
+ if (o instanceof SecretKeySpec)
{
- if (key[i] != okey[i])
+ byte[] okey = ((SecretKeySpec) o).getEncoded();
+ if (key.length != okey.length)
return false;
+ for (int i = 0; i < key.length; i++)
+ {
+ if (key[i] != okey[i])
+ return false;
+ }
+ return algorithm.equals(((SecretKeySpec) o).getAlgorithm());
+ }
+ else
+ {
+ return false;
}
- return algorithm.equals(((SecretKeySpec) o).getAlgorithm());
}
public int hashCode()
diff --git a/javax/imageio/spi/IIORegistry.java b/javax/imageio/spi/IIORegistry.java
index c484ff2f5..e762a9627 100644
--- a/javax/imageio/spi/IIORegistry.java
+++ b/javax/imageio/spi/IIORegistry.java
@@ -49,6 +49,7 @@ import java.util.Iterator;
import gnu.javax.imageio.bmp.BMPImageReaderSpi;
import gnu.javax.imageio.bmp.BMPImageWriterSpi;
import gnu.javax.imageio.gif.GIFImageReaderSpi;
+import gnu.javax.imageio.png.PNGImageReaderSpi;
public final class IIORegistry extends ServiceRegistry
{
@@ -85,7 +86,8 @@ public final class IIORegistry extends ServiceRegistry
super(defaultCategories.iterator());
// XXX: Register built-in Spis here.
- registerServiceProvider(new GIFImageReaderSpi()); // Register GIF decoder
+ registerServiceProvider(new PNGImageReaderSpi()); // Register PNG decoder.
+ registerServiceProvider(new GIFImageReaderSpi()); // Register GIF decoder.
registerServiceProvider(new BMPImageReaderSpi());
registerServiceProvider(new BMPImageWriterSpi());
diff --git a/javax/management/BadAttributeValueExpException.java b/javax/management/BadAttributeValueExpException.java
new file mode 100644
index 000000000..fbdf1deca
--- /dev/null
+++ b/javax/management/BadAttributeValueExpException.java
@@ -0,0 +1,91 @@
+/* BadAttributeValueExpException.java -- Thrown by invalid query attributes.
+ 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 javax.management;
+
+/**
+ * Thrown when the value of an a attribute passed to a query proves to
+ * be invalid. This exception is only used internally by the Java
+ * management API and is not exposed to user code.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class BadAttributeValueExpException
+ extends Exception
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -3105272988410493376L;
+
+ /**
+ * The attribute value that caused the exception.
+ */
+ private Object val;
+
+ /**
+ * Constructs a new <code>BadAttributeValueExpException</code>
+ * using the specified object to represent the invalid value.
+ *
+ * @param val the inappropriate value.
+ */
+ public BadAttributeValueExpException(Object val)
+ {
+ super();
+ this.val = val;
+ }
+
+ /**
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.BadAttributeValueExpException</code>)
+ * and the invalid value.
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ return getClass().getName()
+ + "[val=" + val
+ + "]";
+ }
+
+}
+
diff --git a/javax/management/BadStringOperationException.java b/javax/management/BadStringOperationException.java
new file mode 100644
index 000000000..8e5949ef7
--- /dev/null
+++ b/javax/management/BadStringOperationException.java
@@ -0,0 +1,92 @@
+/* BadStringOperationException.java -- Thrown by invalid query attributes.
+ 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 javax.management;
+
+/**
+ * Thrown when a string-based operation passed to a query proves to
+ * be invalid. This exception is only used internally by the Java
+ * management API and is not exposed to user code.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class BadStringOperationException
+ extends Exception
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 7802201238441662100L;
+
+ /**
+ * The operation that caused the exception.
+ */
+ private String op;
+
+ /**
+ * Constructs a new <code>BadStringOperationException</code>
+ * using the specified object to represent the invalid string
+ * operation.
+ *
+ * @param op the inappropriate string operation.
+ */
+ public BadStringOperationException(String op)
+ {
+ super();
+ this.op = op;
+ }
+
+ /**
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.BadStringOperationException</code>)
+ * and the invalid string operation.
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ return getClass().getName()
+ + "[op=" + op
+ + "]";
+ }
+
+}
+
diff --git a/javax/management/InstanceAlreadyExistsException.java b/javax/management/InstanceAlreadyExistsException.java
new file mode 100644
index 000000000..c783208cb
--- /dev/null
+++ b/javax/management/InstanceAlreadyExistsException.java
@@ -0,0 +1,76 @@
+/* InstanceAlreadyExistsException.java -- Thrown by invalid values.
+ 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 javax.management;
+
+/**
+ * Thrown when an attempt to register a bean is made, and
+ * the bean is already registered.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class InstanceAlreadyExistsException
+ extends OperationsException
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 8893743928912733931L;
+
+ /**
+ * Constructs a new <code>InstanceAlreadyExistsException</code>.
+ */
+ public InstanceAlreadyExistsException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>InstanceAlreadyExistsException</code>
+ * with the specified message.
+ *
+ * @param message the error message to give to the user.
+ */
+ public InstanceAlreadyExistsException(String message)
+ {
+ super(message);
+ }
+
+}
+
diff --git a/javax/management/InstanceNotFoundException.java b/javax/management/InstanceNotFoundException.java
new file mode 100644
index 000000000..4d209fc47
--- /dev/null
+++ b/javax/management/InstanceNotFoundException.java
@@ -0,0 +1,76 @@
+/* InstanceNotFoundException.java -- Thrown by invalid values.
+ 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 javax.management;
+
+/**
+ * Thrown when an attempt to locate a bean is made, and
+ * the bean does not exist in the repository.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class InstanceNotFoundException
+ extends OperationsException
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -882579438394773049L;
+
+ /**
+ * Constructs a new <code>InstanceNotFoundException</code>.
+ */
+ public InstanceNotFoundException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>InstanceNotFoundException</code>
+ * with the specified message.
+ *
+ * @param message the error message to give to the user.
+ */
+ public InstanceNotFoundException(String message)
+ {
+ super(message);
+ }
+
+}
+
diff --git a/javax/management/IntrospectionException.java b/javax/management/IntrospectionException.java
new file mode 100644
index 000000000..3b9d4b1ef
--- /dev/null
+++ b/javax/management/IntrospectionException.java
@@ -0,0 +1,78 @@
+/* IntrospectionException.java -- Thrown by bean introspection methods.
+ 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 javax.management;
+
+/**
+ * A general for all exceptions thrown during introspection
+ * operations on management beans. For example, such an
+ * exception may be thrown while constructing one of
+ * the <code>MBeanXXXInfo</code> classes.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class IntrospectionException
+ extends OperationsException
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 1054516935875481725L;
+
+ /**
+ * Constructs a new <code>IntrospectionException</code>.
+ */
+ public IntrospectionException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>IntrospectionException</code>
+ * with the specified message.
+ *
+ * @param message the error message to give to the user.
+ */
+ public IntrospectionException(String message)
+ {
+ super(message);
+ }
+
+}
+
diff --git a/javax/management/InvalidApplicationException.java b/javax/management/InvalidApplicationException.java
new file mode 100644
index 000000000..0bcf2d6cb
--- /dev/null
+++ b/javax/management/InvalidApplicationException.java
@@ -0,0 +1,92 @@
+/* InvalidApplicationException.java -- Thrown by invalid query attributes.
+ 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 javax.management;
+
+/**
+ * Thrown when a query or attribute is applied to a management bean
+ * which is of the wrong class. This exception is only used
+ * internally by the Java management API and is not exposed to user
+ * code.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class InvalidApplicationException
+ extends Exception
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -3048022274675537269L;
+
+ /**
+ * The attribute value that caused the exception.
+ */
+ private Object val;
+
+ /**
+ * Constructs a new <code>InvalidApplicationException</code>
+ * using the specified object to represent the invalid value.
+ *
+ * @param val the inappropriate expression.
+ */
+ public InvalidApplicationException(Object val)
+ {
+ super();
+ this.val = val;
+ }
+
+ /**
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.InvalidApplicationException</code>)
+ * and the invalid expression.
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ return getClass().getName()
+ + "[val=" + val
+ + "]";
+ }
+
+}
+
diff --git a/javax/management/ListenerNotFoundException.java b/javax/management/ListenerNotFoundException.java
new file mode 100644
index 000000000..ea3cb7416
--- /dev/null
+++ b/javax/management/ListenerNotFoundException.java
@@ -0,0 +1,75 @@
+/* ListenerNotFoundException.java -- Thrown when a listener does not exist.
+ 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 javax.management;
+
+/**
+ * Thrown when a requested listener does not exist.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class ListenerNotFoundException
+ extends OperationsException
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -7242605822448519061L;
+
+ /**
+ * Constructs a new <code>ListenerNotFoundException</code>.
+ */
+ public ListenerNotFoundException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>ListenerNotFoundException</code>
+ * with the specified message.
+ *
+ * @param message the error message to give to the user.
+ */
+ public ListenerNotFoundException(String message)
+ {
+ super(message);
+ }
+
+}
+
diff --git a/javax/management/MBeanAttributeInfo.java b/javax/management/MBeanAttributeInfo.java
new file mode 100644
index 000000000..bded7e41a
--- /dev/null
+++ b/javax/management/MBeanAttributeInfo.java
@@ -0,0 +1,301 @@
+/* MBeanAttributeInfo.java -- Information about an attribute of a bean.
+ 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 javax.management;
+
+import java.lang.reflect.Method;
+
+/**
+ * Describes the attributes of a management bean.
+ * The information in this class is immutable as standard.
+ * Of course, subclasses may change this, but this
+ * behaviour is not recommended.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class MBeanAttributeInfo
+ extends MBeanFeatureInfo
+ implements Cloneable
+{
+
+ /**
+ * The type of the attribute.
+ *
+ * @serial the attribute type.
+ */
+ private String attributeType;
+
+ /**
+ * True if the attribute's value can be changed.
+ *
+ * @serial true if the value can be changed.
+ */
+ private boolean isWrite;
+
+ /**
+ * True if the attribute's value can be read.
+ *
+ * @serial true if the value can be read.
+ */
+ private boolean isRead;
+
+ /**
+ * True if the attribute is a boolean and thus
+ * has a isXXX accessor rather than a getXXX accessor.
+ *
+ * @serial true if the attribute has an isXXX accessor.
+ */
+ private boolean is;
+
+ /**
+ * Constructs a new {@link MBeanAttributeInfo} using the specified
+ * name and description, with the given accessor and mutator
+ * methods. A <code>null</code> value for the accessor method
+ * indicates that the value can not be read. A <code>null</code>
+ * value for the mutator method indicates that the value can not be
+ * changed.
+ *
+ * @param name the name of the attribute.
+ * @param desc a description of the attribute.
+ * @param getter the accessor method, or <code>null</code> if the value
+ * can not be read.
+ * @param setter the mutator method, or <code>null</code> if the value
+ * can not be changed.
+ * @throws IntrospectionException if both the accessor and mutator method
+ * are <code>null</code>.
+ */
+ public MBeanAttributeInfo(String name, String desc,
+ Method getter, Method setter)
+ throws IntrospectionException
+ {
+ super(name, desc);
+ if (getter == null && setter == null)
+ throw new IntrospectionException("Both the getter and setter methods can " +
+ "not be null.");
+ if (getter == null)
+ {
+ attributeType = setter.getParameterTypes()[0].getName();
+ isRead = false;
+ is = false;
+ }
+ else
+ {
+ attributeType = getter.getReturnType().getName();
+ isRead = true;
+ is = getter.getName().startsWith("is");
+ }
+ if (setter != null)
+ isWrite = true;
+ }
+
+ /**
+ * Constructs a new {@link MBeanAttributeInfo} using the specified
+ * name, description and type with the given settings for the accessor
+ * and mutator methods.
+ *
+ * @param name the name of the attribute.
+ * @param type the type of the attribute, in the form of its class name.
+ * @param desc a description of the attribute.
+ * @param isReadable true if the attribute's value can be read.
+ * @param isWritable true if the attribute's value can be changed.
+ * @param isIs true if the attribute uses an accessor of the form isXXX.
+ * @throws IllegalArgumentException if the attribute is both unreadable
+ * and unwritable.
+ */
+ public MBeanAttributeInfo(String name, String type, String desc,
+ boolean isReadable, boolean isWritable,
+ boolean isIs)
+ {
+ super(name, desc);
+ if (!isReadable && !isWritable)
+ throw new IllegalArgumentException("The attribute can not be both " +
+ "unreadable and unwritable.");
+ attributeType = type;
+ isRead = isReadable;
+ isWrite = isWritable;
+ is = isIs;
+ }
+
+ /**
+ * Returns a clone of this instance. The clone is created
+ * using just the method provided by {@link java.lang.Object}.
+ * Thus, the clone is just a shallow clone as returned by
+ * that method, and does not contain any deeper cloning based
+ * on the subject of this class.
+ *
+ * @return a clone of this instance.
+ * @see java.lang.Cloneable
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ /* This shouldn't happen; we implement Cloneable */
+ throw new IllegalStateException("clone() called on " +
+ "non-cloneable object.");
+ }
+ }
+
+ /**
+ * Compares this feature with the supplied object. This
+ * returns true iff the object is an instance of
+ * {@link MBeanAttributeInfo}, {@link Object#equals()}
+ * returns true for a comparison of both the name and
+ * description of this attribute with that of the specified
+ * object (performed by the superclass), and the type and
+ * boolean flags of the two instances are equal.
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link MBeanAttributeInfo}
+ * instance,
+ * <code>name.equals(object.getName())</code>,
+ * <code>description.equals(object.getDescription())</code>,
+ * <code>attributeType.equals(object.getType())</code>,
+ * <code>isRead == object.isReadable()</code>,
+ * <code>isWrite == object.isWritable()</code>,
+ * <code>is == object.isIs()</code>
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof MBeanAttributeInfo))
+ return false;
+ if (!(super.equals(obj)))
+ return false;
+ MBeanAttributeInfo o = (MBeanAttributeInfo) obj;
+ return (attributeType.equals(o.getType()) &&
+ isRead == o.isReadable() &&
+ isWrite == o.isWritable() &&
+ is == o.isIs());
+ }
+
+ /**
+ * Returns the type of this attribute, in the form of its class name.
+ *
+ * @return the type of this attribute.
+ */
+ public String getType()
+ {
+ return attributeType;
+ }
+
+ /**
+ * Returns the hashcode of the attribute information as the sum of
+ * the hashcode of the superclass, the hashcode of the type,
+ * the hashcode of {@link #isReadable()}, twice the hashcode
+ * of {@link #isWritable()} and four times the hashcode
+ * of {@link #isIs()}.
+ *
+ * @return the hashcode of the attribute information.
+ */
+ public int hashCode()
+ {
+ return super.hashCode() + attributeType.hashCode()
+ + Boolean.valueOf(isRead).hashCode()
+ + (2 * Boolean.valueOf(isWrite).hashCode())
+ + (4 * Boolean.valueOf(is).hashCode());
+ }
+
+ /**
+ * Returns true if the accessor method of this attribute
+ * is of the form <code>isXXX</code>.
+ *
+ * @return true if the accessor takes the form <code>isXXX</code>.
+ */
+ public boolean isIs()
+ {
+ return is;
+ }
+
+ /**
+ * Returns true if value of this attribute can be read.
+ *
+ * @return true if the value of the attribute can be read.
+ */
+ public boolean isReadable()
+ {
+ return isRead;
+ }
+
+ /**
+ * Returns true if the value of this attribute can be changed.
+ *
+ * @return true if the value of the attribute can be changed.
+ */
+ public boolean isWritable()
+ {
+ return isWrite;
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.MBeanAttributeInfo</code>),
+ * the name, description and type of the attribute and the
+ * current settings of the {@link #isReadable()},
+ * {@link #isWritable()} and {@link #isIs()} properties.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ {
+ super.toString();
+ string = string.substring(0, string.length() - 1)
+ + ",type=" + attributeType
+ + ",isReadable=" + (isRead ? "yes" : "no")
+ + ",isWritable=" + (isWrite ? "yes" : "no")
+ + ",isIs=" + (is ? "yes" : "no")
+ + "]";
+ }
+ return string;
+ }
+
+}
diff --git a/javax/management/MBeanConstructorInfo.java b/javax/management/MBeanConstructorInfo.java
new file mode 100644
index 000000000..9ddd432a8
--- /dev/null
+++ b/javax/management/MBeanConstructorInfo.java
@@ -0,0 +1,232 @@
+/* MBeanConstructorInfo.java -- Information about a bean's constructor.
+ 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 javax.management;
+
+import java.lang.reflect.Constructor;
+
+import java.util.Arrays;
+
+/**
+ * Describes the constructors of a management bean.
+ * The information in this class is immutable as standard.
+ * Of course, subclasses may change this, but this
+ * behaviour is not recommended.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class MBeanConstructorInfo
+ extends MBeanFeatureInfo
+ implements Cloneable
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 4433990064191844427L;
+
+ /**
+ * The signature of the constructor i.e. the argument types.
+ */
+ private MBeanParameterInfo[] signature;
+
+ /**
+ * Constructs a @link{MBeanConstructorInfo} with the specified
+ * description using the given constructor. Each parameter is
+ * described merely by its type; the name and description are
+ * <code>null</code>.
+ *
+ * @param desc a description of the attribute.
+ * @param cons the constructor.
+ */
+ public MBeanConstructorInfo(String desc, Constructor cons)
+ {
+ super(cons.getName(), desc);
+ Class[] paramTypes = cons.getParameterTypes();
+ signature = new MBeanParameterInfo[paramTypes.length];
+ for (int a = 0; a < paramTypes.length; ++a)
+ signature[a] = new MBeanParameterInfo(null,
+ paramTypes[a].getName(),
+ null);
+ }
+
+ /**
+ * Constructs a @link{MBeanConstructorInfo} with the specified
+ * name, description and parameter information. A <code>null</code>
+ * value for the parameter information is the same as passing in
+ * an empty array. A copy of the parameter array is taken, so
+ * later changes have no effect.
+ *
+ * @param name the name of the constructor.
+ * @param desc a description of the constructor.
+ * @param sig the signature of the constructor, as a series
+ * of {@link MBeanParameterInfo} objects, one for
+ * each parameter.
+ */
+ public MBeanConstructorInfo(String name, String desc,
+ MBeanParameterInfo[] sig)
+ {
+ super(name, desc);
+ if (sig == null)
+ signature = new MBeanParameterInfo[0];
+ else
+ {
+ signature = new MBeanParameterInfo[sig.length];
+ System.arraycopy(sig, 0, signature, 0, sig.length);
+ }
+ }
+
+ /**
+ * Returns a clone of this instance. The clone is created
+ * using just the method provided by {@link java.lang.Object}.
+ * Thus, the clone is just a shallow clone as returned by
+ * that method, and does not contain any deeper cloning based
+ * on the subject of this class.
+ *
+ * @return a clone of this instance.
+ * @see java.lang.Cloneable
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ /* This shouldn't happen; we implement Cloneable */
+ throw new IllegalStateException("clone() called on " +
+ "non-cloneable object.");
+ }
+ }
+
+ /**
+ * Compares this feature with the supplied object. This returns
+ * true iff the object is an instance of {@link
+ * MBeanConstructorInfo}, {@link Object#equals()} returns true for a
+ * comparison of both the name and description of this notification
+ * with that of the specified object (performed by the superclass),
+ * and the two signature arrays contain the same elements in the
+ * same order (but one may be longer than the other).
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link MBeanConstructorInfo}
+ * instance,
+ * <code>name.equals(object.getName())</code>,
+ * <code>description.equals(object.getDescription())</code>
+ * and the corresponding elements of the signature arrays are
+ * equal.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof MBeanConstructorInfo))
+ return false;
+ if (!(super.equals(obj)))
+ return false;
+ MBeanConstructorInfo o = (MBeanConstructorInfo) obj;
+ MBeanParameterInfo[] sig = o.getSignature();
+ for (int a = 0; a < signature.length; ++a)
+ {
+ if (a == sig.length)
+ return true;
+ if (!(signature[a].equals(sig[a])))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns the constructor's signature, in the form of
+ * information on each parameter. Each parameter is
+ * described by an instance of {@link MBeanParameterInfo}.
+ * The returned array is a shallow copy of the array used
+ * by this instance, so changing which elements are stored
+ * in the array won't affect the array used by this, but
+ * changing the actual elements will affect the ones used
+ * here.
+ *
+ * @return an array of {@link MBeanParameterInfo} objects,
+ * describing the constructor parameters.
+ */
+ public MBeanParameterInfo[] getSignature()
+ {
+ return (MBeanParameterInfo[]) signature.clone();
+ }
+
+ /**
+ * Returns the hashcode of the constructor information as the sum
+ * of the hashcode of the superclass and the hashcode of the parameter
+ * array.
+ *
+ * @return the hashcode of the constructor information.
+ */
+ public int hashCode()
+ {
+ return super.hashCode() + Arrays.hashCode(signature);
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.MBeanConstructorInfo</code>),
+ * the name and description of the constructor and the
+ * contents of the array of parameters.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ {
+ super.toString();
+ string = string.substring(0, string.length() - 1)
+ + ",signature=" + Arrays.toString(signature)
+ + "]";
+ }
+ return string;
+ }
+
+}
diff --git a/javax/management/MBeanFeatureInfo.java b/javax/management/MBeanFeatureInfo.java
index 72dc85996..74a030387 100644
--- a/javax/management/MBeanFeatureInfo.java
+++ b/javax/management/MBeanFeatureInfo.java
@@ -77,6 +77,11 @@ public class MBeanFeatureInfo
protected String name;
/**
+ * The <code>toString()</code> result of this instance.
+ */
+ transient String string;
+
+ /**
* Constructs a new {@link MBeanFeatureInfo} with the specified
* name and description.
*
@@ -141,14 +146,41 @@ public class MBeanFeatureInfo
/**
* Returns the hashcode of the feature as
- * the multiplication of the hashcodes of
- * its name and description.
+ * the sum of the hashcodes of its name
+ * and description.
*
* @return the hashcode of this feature.
*/
public int hashCode()
{
- return name.hashCode() * description.hashCode();
+ return (name == null ? -1 : name.hashCode())
+ + (description == null ? -1 : description.hashCode());
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.MBeanFeatureInfo</code>) and
+ * the name and description of the feature.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ string = getClass().getName()
+ + "[name=" + name
+ + ",desc=" + description
+ + "]";
+ return string;
}
}
diff --git a/javax/management/MBeanInfo.java b/javax/management/MBeanInfo.java
index 3aad20e31..d30de0499 100644
--- a/javax/management/MBeanInfo.java
+++ b/javax/management/MBeanInfo.java
@@ -39,6 +39,8 @@ package javax.management;
import java.io.Serializable;
+import java.util.Arrays;
+
/**
* <p>
* Describes the interface of a management bean. This allows
@@ -104,6 +106,91 @@ public class MBeanInfo
private String className;
/**
+ * Descriptions of the attributes provided by the bean.
+ */
+ private MBeanAttributeInfo[] attributes;
+
+ /**
+ * Descriptions of the operations provided by the bean.
+ */
+ private MBeanOperationInfo[] operations;
+
+ /**
+ * Descriptions of the bean's constructors.
+ */
+ private MBeanConstructorInfo[] constructors;
+
+ /**
+ * Descriptions of the notifications emitted by the bean.
+ *
+ * @serial The bean's notifications.
+ */
+ private MBeanNotificationInfo[] notifications;
+
+ /**
+ * The <code>toString()</code> result of this instance.
+ */
+ private transient String string;
+
+ /**
+ * Constructs a new {@link MBeanInfo} using the supplied
+ * class name and description with the given attributes,
+ * operations, constructors and notifications. The class
+ * name does not have to actually specify a valid class that
+ * can be loaded by the MBean server or class loader; it merely
+ * has to be a syntactically correct class name. Any of the
+ * arrays may be <code>null</code>; this will be treated as if
+ * an empty array was supplied. A copy of the arrays is
+ * taken, so later changes have no effect.
+ *
+ * @param name the name of the class this instance describes.
+ * @param desc a description of the bean.
+ * @param attribs the attribute descriptions for the bean,
+ * or <code>null</code>.
+ * @param cons the constructor descriptions for the bean,
+ * or <code>null</code>.
+ * @param ops the operation descriptions for the bean,
+ * or <code>null</code>.
+ * @param notifs the notification descriptions for the bean,
+ * or <code>null</code>.
+ */
+ public MBeanInfo(String name, String desc, MBeanAttributeInfo[] attribs,
+ MBeanConstructorInfo[] cons, MBeanOperationInfo[] ops,
+ MBeanNotificationInfo[] notifs)
+ {
+ className = name;
+ description = desc;
+ if (attribs == null)
+ attributes = new MBeanAttributeInfo[0];
+ else
+ {
+ attributes = new MBeanAttributeInfo[attribs.length];
+ System.arraycopy(attribs, 0, attributes, 0, attribs.length);
+ }
+ if (cons == null)
+ constructors = new MBeanConstructorInfo[0];
+ else
+ {
+ constructors = new MBeanConstructorInfo[cons.length];
+ System.arraycopy(cons, 0, constructors, 0, cons.length);
+ }
+ if (ops == null)
+ operations = new MBeanOperationInfo[0];
+ else
+ {
+ operations = new MBeanOperationInfo[ops.length];
+ System.arraycopy(ops, 0, operations, 0, ops.length);
+ }
+ if (notifs == null)
+ notifications = new MBeanNotificationInfo[0];
+ else
+ {
+ notifications = new MBeanNotificationInfo[notifs.length];
+ System.arraycopy(notifs, 0, notifications, 0, notifs.length);
+ }
+ }
+
+ /**
* Returns a shallow clone of the information. This is
* simply a new copy of each string and a clone
* of each array, which still references the same objects,
@@ -130,6 +217,82 @@ public class MBeanInfo
}
/**
+ * Compares this feature with the supplied object. This returns
+ * true iff the object is an instance of {@link MBeanInfo} and
+ * {@link Object#equals()} returns true for a comparison of the
+ * class name and description, and the arrays each contain the same
+ * elements in the same order (but one may be longer than the
+ * other).
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link MBeanInfo}
+ * instance,
+ * <code>className.equals(object.getClassName())</code>,
+ * <code>description.equals(object.getDescription())</code>
+ * and the corresponding elements of the arrays are
+ * equal.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof MBeanInfo))
+ return false;
+ if (!(super.equals(obj)))
+ return false;
+ MBeanInfo o = (MBeanInfo) obj;
+ MBeanAttributeInfo[] attr = o.getAttributes();
+ for (int a = 0; a < attributes.length; ++a)
+ {
+ if (a == attr.length)
+ return true;
+ if (!(attributes[a].equals(attr[a])))
+ return false;
+ }
+ MBeanConstructorInfo[] cons = o.getConstructors();
+ for (int a = 0; a < constructors.length; ++a)
+ {
+ if (a == cons.length)
+ return true;
+ if (!(constructors[a].equals(cons[a])))
+ return false;
+ }
+ MBeanOperationInfo[] ops = o.getOperations();
+ for (int a = 0; a < operations.length; ++a)
+ {
+ if (a == ops.length)
+ return true;
+ if (!(operations[a].equals(ops[a])))
+ return false;
+ }
+ MBeanNotificationInfo[] notifs = o.getNotifications();
+ for (int a = 0; a < notifications.length; ++a)
+ {
+ if (a == notifs.length)
+ return true;
+ if (!(notifications[a].equals(notifs[a])))
+ return false;
+ }
+ return (className.equals(o.getClassName()) &&
+ description.equals(o.getDescription()));
+ }
+
+ /**
+ * Returns descriptions of each of the attributes provided
+ * by this management bean. The returned value is a shallow
+ * copy of the attribute array maintained by this instance.
+ * Hence, changing the elements of the returned array will not
+ * affect the attribute array, and the elements (instances
+ * of the {@link MBeanAttributeInfo} class) are immutable.
+ *
+ * @return an array of {@link MBeanAttributeInfo} objects,
+ * representing the attributes emitted by this
+ * management bean.
+ */
+ public MBeanAttributeInfo[] getAttributes()
+ {
+ return (MBeanAttributeInfo[]) attributes.clone();
+ }
+
+ /**
* Returns the class name of the management bean.
*
* @return the bean's class name.
@@ -140,6 +303,23 @@ public class MBeanInfo
}
/**
+ * Returns descriptions of each of the constructors provided
+ * by this management bean. The returned value is a shallow
+ * copy of the constructor array maintained by this instance.
+ * Hence, changing the elements of the returned array will not
+ * affect the constructor array, and the elements (instances
+ * of the {@link MBeanConstructorInfo} class) are immutable.
+ *
+ * @return an array of {@link MBeanConstructorInfo} objects,
+ * representing the constructors emitted by this
+ * management bean.
+ */
+ public MBeanConstructorInfo[] getConstructors()
+ {
+ return (MBeanConstructorInfo[]) constructors.clone();
+ }
+
+ /**
* Returns a description of the management bean.
*
* @return the bean's description.
@@ -149,4 +329,82 @@ public class MBeanInfo
return description;
}
+ /**
+ * Returns descriptions of each of the notifications emitted
+ * by this management bean. The returned value is a shallow
+ * copy of the notification array maintained by this instance.
+ * Hence, changing the elements of the returned array will not
+ * affect the notification array, and the elements (instances
+ * of the {@link MBeanNotificationInfo} class) are immutable.
+ *
+ * @return an array of {@link MBeanNotificationInfo} objects,
+ * representing the notifications emitted by this
+ * management bean.
+ */
+ public MBeanNotificationInfo[] getNotifications()
+ {
+ return (MBeanNotificationInfo[]) notifications.clone();
+ }
+
+ /**
+ * Returns descriptions of each of the operations provided
+ * by this management bean. The returned value is a shallow
+ * copy of the operation array maintained by this instance.
+ * Hence, changing the elements of the returned array will not
+ * affect the operation array, and the elements (instances
+ * of the {@link MBeanOperationInfo} class) are immutable.
+ *
+ * @return an array of {@link MBeanOperationInfo} objects,
+ * representing the operations emitted by this
+ * management bean.
+ */
+ public MBeanOperationInfo[] getOperations()
+ {
+ return (MBeanOperationInfo[]) operations.clone();
+ }
+
+ /**
+ * Returns the hashcode of the information as the sum of the
+ * hashcode of the classname, description and each array.
+ *
+ * @return the hashcode of the information.
+ */
+ public int hashCode()
+ {
+ return className.hashCode() + description.hashCode()
+ + Arrays.hashCode(attributes) + Arrays.hashCode(constructors)
+ + Arrays.hashCode(operations) + Arrays.hashCode(notifications);
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.MBeanInfo</code>),
+ * the name and description of the bean and the contents
+ * of the four arrays.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ string = getClass().getName()
+ + "[name=" + className
+ + ",desc=" + description
+ + ",attributes=" + Arrays.toString(attributes)
+ + ",constructors=" + Arrays.toString(constructors)
+ + ",operations=" + Arrays.toString(operations)
+ + ",notifications=" + Arrays.toString(notifications)
+ + "]";
+ return string;
+ }
+
}
diff --git a/javax/management/MBeanNotificationInfo.java b/javax/management/MBeanNotificationInfo.java
new file mode 100644
index 000000000..ba4077e8f
--- /dev/null
+++ b/javax/management/MBeanNotificationInfo.java
@@ -0,0 +1,227 @@
+/* MBeanNotificationInfo.java -- Information about a bean's notification.
+ 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 javax.management;
+
+import java.util.Arrays;
+
+/**
+ * <p>
+ * Describes the notifications emitted by a management bean.
+ * An instance of this class is specific to notifications
+ * involving a particular type of object. A new instance
+ * should be created for each Java class used for notifications,
+ * and the Java class name forms the name of the instance.
+ * Each instance lists a number of notification types; these
+ * are not types in the sense of different Java classes, but
+ * instead form the names of notifications following the same
+ * syntax as Java property and package names.
+ * </p>
+ * <p>
+ * For instance, a management bean may emit two notifications
+ * containing {@link java.lang.String} objects. Both would be described
+ * using one instance of this class, with a member of the array
+ * returned by {@link #getNotifTypes()} for each one. If another
+ * notification containing a {@link java.util.Date} object were to
+ * be added, this would require a new instance of this class.
+ * </p>
+ * <p>
+ * The information in this class is immutable as standard.
+ * Of course, subclasses may change this, but this
+ * behaviour is not recommended.
+ * </p>
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class MBeanNotificationInfo
+ extends MBeanFeatureInfo
+ implements Cloneable
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -3888371564530107064L;
+
+ /**
+ * The types of notification described by this instance.
+ *
+ * @serial the types of notification.
+ */
+ private String[] types;
+
+ /**
+ * Constructs a new {@link MBeanNotificationInfo} with the
+ * specified name, description and notification types. The
+ * notification types array may be <code>null</code> or of
+ * zero length, in order to indicate the absence of any types.
+ *
+ * @param types an array of {@link java.lang.String} objects,
+ * containing the names of the notifications emitted
+ * of this Java type. The names use the dot notation
+ * familiar from Java property and package names.
+ * @param name the name of the Java class the notifications described
+ * by this object are instances of.
+ * @param description a description of the data.
+ * @throws IllegalArgumentException for some reason...
+ */
+ public MBeanNotificationInfo(String[] types, String name,
+ String description)
+ {
+ super(name, description);
+ this.types = types;
+ }
+
+ /**
+ * Returns a clone of this instance. The clone is created
+ * using just the method provided by {@link java.lang.Object}.
+ * Thus, the clone is just a shallow clone as returned by
+ * that method, and does not contain any deeper cloning based
+ * on the subject of this class.
+ *
+ * @return a clone of this instance.
+ * @see java.lang.Cloneable
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ /* This shouldn't happen; we implement Cloneable */
+ throw new IllegalStateException("clone() called on " +
+ "non-cloneable object.");
+ }
+ }
+
+ /**
+ * Compares this feature with the supplied object. This returns
+ * true iff the object is an instance of {@link
+ * MBeanNotificationInfo}, {@link Object#equals()} returns true for
+ * a comparison of both the name and description of this
+ * notification with that of the specified object, and the two
+ * notification type arrays contain the same elements in the same
+ * order (but one may be longer than the other).
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link MBeanNotificationInfo}
+ * instance,
+ * <code>name.equals(object.getName())</code>,
+ * <code>description.equals(object.getDescription())</code>
+ * and the corresponding elements of the type arrays are
+ * equal.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof MBeanNotificationInfo)
+ {
+ if (!(super.equals(obj)))
+ return false;
+ MBeanNotificationInfo o = (MBeanNotificationInfo) obj;
+ String[] oTypes = o.getNotifTypes();
+ for (int a = 0; a < types.length; ++a)
+ {
+ if (a == oTypes.length)
+ return true;
+ if (!(types[a].equals(oTypes[a])))
+ return false;
+ }
+ return true;
+ }
+ else
+ return false;
+ }
+
+ /**
+ * Returns the notification types that the management bean may emit.
+ * The notification types are strings using the dot notation
+ * familiar from Java property and package names. Changing the
+ * returned array does not affect the values retained by this
+ * instance.
+ *
+ * @return the notification types.
+ */
+ public String[] getNotifTypes()
+ {
+ return types;
+ }
+
+ /**
+ * Returns the hashcode of the notification information as the sum
+ * of the hashcode of the superclass and the hashcode of the types
+ * array.
+ *
+ * @return the hashcode of the notification information.
+ */
+ public int hashCode()
+ {
+ return super.hashCode() + Arrays.hashCode(types);
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.MBeanNotificationInfo</code>),
+ * the name and description of the notification and the
+ * contents of the array of types.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ {
+ super.toString();
+ string = string.substring(0, string.length() - 1)
+ + ",types=" + Arrays.toString(types)
+ + "]";
+ }
+ return string;
+ }
+
+}
diff --git a/javax/management/MBeanOperationInfo.java b/javax/management/MBeanOperationInfo.java
new file mode 100644
index 000000000..2a78d19d9
--- /dev/null
+++ b/javax/management/MBeanOperationInfo.java
@@ -0,0 +1,348 @@
+/* MBeanOperationInfo.java -- Information about a bean's operations.
+ 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 javax.management;
+
+import java.lang.reflect.Method;
+
+import java.util.Arrays;
+
+/**
+ * Describes the operations of a management bean.
+ * The information in this class is immutable as standard.
+ * Of course, subclasses may change this, but this
+ * behaviour is not recommended.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class MBeanOperationInfo
+ extends MBeanFeatureInfo
+ implements Cloneable
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -6178860474881375330L;
+
+ /**
+ * Used to signify that the operation merely provides information
+ * (akin to an accessor).
+ */
+ public static final int INFO = 0;
+
+ /**
+ * Used to signify that the operation makes some change to the
+ * state of the bean (akin to a mutator).
+ */
+ public static final int ACTION = 1;
+
+ /**
+ * Used to signify that the operation makes some state change
+ * to the bean and also returns information.
+ */
+ public static final int ACTION_INFO = 2;
+
+ /**
+ * Used to signify that the behaviour of the operation is
+ * unknown.
+ */
+ public static final int UNKNOWN = 3;
+
+ /**
+ * The return type of the method, in the form of its class name.
+ */
+ private String type;
+
+ /**
+ * The signature of the constructor i.e. the argument types.
+ */
+ private MBeanParameterInfo[] signature;
+
+ /**
+ * The impact of the method, as one of {@link #INFO}, {@link #ACTION},
+ * {@link #ACTION_INFO} and {@link #UNKNOWN}.
+ */
+ private int impact;
+
+ /**
+ * Constructs a @link{MBeanOperationInfo} with the specified
+ * description using the given method. Each parameter is
+ * described merely by its type; the name and description are
+ * <code>null</code>. The return type and impact of the
+ * method are determined from the {@link Method} instance.
+ *
+ * @param desc a description of the attribute.
+ * @param method the method.
+ */
+ public MBeanOperationInfo(String desc, Method method)
+ {
+ super(method.getName(), desc);
+ Class[] paramTypes = method.getParameterTypes();
+ signature = new MBeanParameterInfo[paramTypes.length];
+ for (int a = 0; a < paramTypes.length; ++a)
+ signature[a] = new MBeanParameterInfo(null,
+ paramTypes[a].getName(),
+ null);
+ type = method.getReturnType().getName();
+ if (method.getReturnType() == Void.TYPE)
+ {
+ if (paramTypes.length == 0)
+ impact = UNKNOWN;
+ else
+ impact = ACTION;
+ }
+ else
+ {
+ if (paramTypes.length == 0)
+ impact = INFO;
+ else
+ impact = ACTION_INFO;
+ }
+ }
+
+ /**
+ * Constructs a @link{MBeanOperationInfo} with the specified name,
+ * description, parameter information, return type and impact. A
+ * <code>null</code> value for the parameter information is the same
+ * as passing in an empty array. A copy of the parameter array is
+ * taken, so later changes have no effect.
+ *
+ * @param name the name of the constructor.
+ * @param desc a description of the attribute.
+ * @param sig the signature of the method, as a series
+ * of {@link MBeanParameterInfo} objects, one for
+ * each parameter.
+ * @param type the return type of the method, as the class name.
+ * @param impact the impact of performing the operation.
+ */
+ public MBeanOperationInfo(String name, String desc,
+ MBeanParameterInfo[] sig, String type,
+ int impact)
+ {
+ super(name, desc);
+ if (sig == null)
+ signature = new MBeanParameterInfo[0];
+ else
+ {
+ signature = new MBeanParameterInfo[sig.length];
+ System.arraycopy(sig, 0, signature, 0, sig.length);
+ }
+ this.type = type;
+ this.impact = impact;
+ }
+
+ /**
+ * Returns a clone of this instance. The clone is created
+ * using just the method provided by {@link java.lang.Object}.
+ * Thus, the clone is just a shallow clone as returned by
+ * that method, and does not contain any deeper cloning based
+ * on the subject of this class.
+ *
+ * @return a clone of this instance.
+ * @see java.lang.Cloneable
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ /* This shouldn't happen; we implement Cloneable */
+ throw new IllegalStateException("clone() called on " +
+ "non-cloneable object.");
+ }
+ }
+
+ /**
+ * Compares this feature with the supplied object. This returns
+ * true iff the object is an instance of {@link
+ * MBeanConstructorInfo}, {@link Object#equals()} returns true for a
+ * comparison of both the name and description of this notification
+ * with that of the specified object (performed by the superclass),
+ * the return type and impact are equal and the two signature arrays
+ * contain the same elements in the same order (but one may be
+ * longer than the other).
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link MBeanOperationInfo}
+ * instance,
+ * <code>name.equals(object.getName())</code>,
+ * <code>description.equals(object.getDescription())</code>,
+ * <code>type.equals(object.getReturnType())</code>,
+ * <code>impact == object.getImpact()</code>,
+ * and the corresponding elements of the signature arrays are
+ * equal.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof MBeanOperationInfo))
+ return false;
+ if (!(super.equals(obj)))
+ return false;
+ MBeanOperationInfo o = (MBeanOperationInfo) obj;
+ MBeanParameterInfo[] sig = o.getSignature();
+ for (int a = 0; a < signature.length; ++a)
+ {
+ if (a == sig.length)
+ return true;
+ if (!(signature[a].equals(sig[a])))
+ return false;
+ }
+ return (type.equals(o.getReturnType()) &&
+ impact == o.getImpact());
+ }
+
+ /**
+ * <p>
+ * Returns the impact of performing this operation.
+ * The value is equal to one of the following:
+ * </p>
+ * <ol>
+ * <li>{@link #INFO} &mdash; the method just returns
+ * information (akin to an accessor).</li>
+ * <li>{@link #ACTION} &mdash; the method just alters
+ * the state of the bean, without returning a value
+ * (akin to a mutator).</li>
+ * <li>{@link #ACTION_INFO} &mdash; the method both makes
+ * state changes and returns a value.</li>
+ * <li>{@link #UNKNOWN} &mdash; the behaviour of the operation
+ * is unknown.</li>
+ * </ol>
+ *
+ * @return the impact of performing the operation.
+ */
+ public int getImpact()
+ {
+ return impact;
+ }
+
+ /**
+ * Returns the return type of the operation, as the class
+ * name.
+ *
+ * @return the return type.
+ */
+ public String getReturnType()
+ {
+ return type;
+ }
+
+ /**
+ * Returns the operation's signature, in the form of
+ * information on each parameter. Each parameter is
+ * described by an instance of {@link MBeanParameterInfo}.
+ * The returned array is a shallow copy of the array used
+ * by this instance, so changing which elements are stored
+ * in the array won't affect the array used by this, but
+ * changing the actual elements will affect the ones used
+ * here.
+ *
+ * @return an array of {@link MBeanParameterInfo} objects,
+ * describing the operation parameters.
+ */
+ public MBeanParameterInfo[] getSignature()
+ {
+ return (MBeanParameterInfo[]) signature.clone();
+ }
+
+ /**
+ * Returns the hashcode of the operation information as the sum of
+ * the hashcode of the superclass, the parameter array, the return
+ * type and the impact factor.
+ *
+ * @return the hashcode of the operation information.
+ */
+ public int hashCode()
+ {
+ return super.hashCode() + Arrays.hashCode(signature)
+ + type.hashCode() + Integer.valueOf(impact).hashCode();
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.MBeanOperationInfo</code>),
+ * the name, description, return type and impact of the
+ * operation and the contents of the array of parameters.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ {
+ String impactString;
+ switch (impact)
+ {
+ case INFO:
+ impactString = "INFO";
+ break;
+ case ACTION:
+ impactString = "ACTION";
+ break;
+ case ACTION_INFO:
+ impactString = "ACTION_INFO";
+ break;
+ case UNKNOWN:
+ impactString = "UNKNOWN";
+ break;
+ default:
+ impactString = "ERRONEOUS VALUE";
+ }
+ super.toString();
+ string = string.substring(0, string.length() - 1)
+ + ",returnType=" + type
+ + ",impact=" + impactString
+ + ",signature=" + Arrays.toString(signature)
+ + "]";
+ }
+ return string;
+ }
+
+}
diff --git a/javax/management/MBeanParameterInfo.java b/javax/management/MBeanParameterInfo.java
new file mode 100644
index 000000000..ee6ef99b8
--- /dev/null
+++ b/javax/management/MBeanParameterInfo.java
@@ -0,0 +1,176 @@
+/* MBeanParameterInfo.java -- Information about an operation's parameters.
+ 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 javax.management;
+
+/**
+ * Describes the parameters of a constructor or operation associated
+ * with a management bean. The information in this class is immutable
+ * as standard. Of course, subclasses may change this, but this
+ * behaviour is not recommended.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class MBeanParameterInfo
+ extends MBeanFeatureInfo
+ implements Cloneable
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 7432616882776782338L;
+
+ /**
+ * The type of the parameter, represented by the class name.
+ */
+ private String type;
+
+ /**
+ * Constructs a new {@link MBeanParameterInfo} using the specified
+ * name, description and type.
+ *
+ * @param name the name of the attribute.
+ * @param type the type of the attribute, in the form of its class name.
+ * @param desc a description of the attribute.
+ */
+ public MBeanParameterInfo(String name, String type, String desc)
+ {
+ super(name, desc);
+ this.type = type;
+ }
+
+ /**
+ * Returns a clone of this instance. The clone is created
+ * using just the method provided by {@link java.lang.Object}.
+ * Thus, the clone is just a shallow clone as returned by
+ * that method, and does not contain any deeper cloning based
+ * on the subject of this class.
+ *
+ * @return a clone of this instance.
+ * @see java.lang.Cloneable
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ /* This shouldn't happen; we implement Cloneable */
+ throw new IllegalStateException("clone() called on " +
+ "non-cloneable object.");
+ }
+ }
+
+ /**
+ * Compares this feature with the supplied object. This returns
+ * true iff the object is an instance of {@link MBeanParameterInfo},
+ * {@link Object#equals()} returns true for a comparison of both the
+ * name and description of this parameter with that of the specified
+ * object (performed by the superclass), and the type of the two
+ * instances is equal.
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link MBeanParameterInfo}
+ * instance,
+ * <code>name.equals(object.getName())</code>,
+ * <code>description.equals(object.getDescription())</code>,
+ * and <code>type.equals(object.getType())</code>.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof MBeanParameterInfo))
+ return false;
+ if (!(super.equals(obj)))
+ return false;
+ MBeanParameterInfo o = (MBeanParameterInfo) obj;
+ return type.equals(o.getType());
+ }
+
+ /**
+ * Returns the type of this attribute, in the form of its class name.
+ *
+ * @return the type of this attribute.
+ */
+ public String getType()
+ {
+ return type;
+ }
+
+ /**
+ * Returns the hashcode of the parameter information as the sum of
+ * the hashcode of the superclass and the hashcode of the type.
+ *
+ * @return the hashcode of the parameter information.
+ */
+ public int hashCode()
+ {
+ return super.hashCode() + type.hashCode();
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.MBeanParameterInfo</code>) along
+ * with the name, description and type of the parameter.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ {
+ super.toString();
+ string = string.substring(0, string.length() - 1)
+ + ",type=" + type
+ + "]";
+ }
+ return string;
+ }
+
+}
diff --git a/javax/management/MBeanRegistrationException.java b/javax/management/MBeanRegistrationException.java
new file mode 100644
index 000000000..9f62b9aa0
--- /dev/null
+++ b/javax/management/MBeanRegistrationException.java
@@ -0,0 +1,84 @@
+/* MBeanRegistrationException.java -- A bean registration exception.
+ 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 javax.management;
+
+/**
+ * Represents an arbitrary exception thrown during registration of a
+ * management bean. When registering a bean causes an exception to be
+ * thrown, the resulting exception is wrapped inside an {@link
+ * MBeanRegistrationException}. Calling {@link getTargetException()}
+ * will return the wrapped exception.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class MBeanRegistrationException
+ extends MBeanException
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 4482382455277067805L;
+
+ /**
+ * Constructs a new <code>MBeanRegistrationException</code> wrapping
+ * the specified exception.
+ *
+ * @param e the exception to be wrapped.
+ */
+ public MBeanRegistrationException(Exception e)
+ {
+ super(e);
+ }
+
+ /**
+ * Constructs a new <code>MBeanRegistrationException</code> wrapping
+ * the specified exception and using the supplied message.
+ *
+ * @param e the exception to be wrapped.
+ * @param message the error message to give to the user.
+ */
+ public MBeanRegistrationException(Exception e, String message)
+ {
+ super(e, message);
+ }
+
+
+}
+
diff --git a/javax/management/MalformedObjectNameException.java b/javax/management/MalformedObjectNameException.java
new file mode 100644
index 000000000..e2f577490
--- /dev/null
+++ b/javax/management/MalformedObjectNameException.java
@@ -0,0 +1,76 @@
+/* MalformedObjectNameException.java -- Thrown by invalid values.
+ 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 javax.management;
+
+/**
+ * Thrown when a string used as an {@link ObjectName}
+ * is invalid.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class MalformedObjectNameException
+ extends OperationsException
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -572689714442915824L;
+
+ /**
+ * Constructs a new <code>MalformedObjectNameException</code>.
+ */
+ public MalformedObjectNameException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>MalformedObjectNameException</code>
+ * with the specified message.
+ *
+ * @param message the error message to give to the user.
+ */
+ public MalformedObjectNameException(String message)
+ {
+ super(message);
+ }
+
+}
+
diff --git a/javax/management/NotCompliantMBeanException.java b/javax/management/NotCompliantMBeanException.java
new file mode 100644
index 000000000..f2252f28b
--- /dev/null
+++ b/javax/management/NotCompliantMBeanException.java
@@ -0,0 +1,78 @@
+/* NotCompliantMBeanException.java -- Thrown due to a non-compliant bean.
+ 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 javax.management;
+
+/**
+ * Thrown when a management bean is passed to a method
+ * (e.g. to an MBean server to be registered) and it
+ * fails to comply with the specifications for such
+ * a bean.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class NotCompliantMBeanException
+ extends OperationsException
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 5175579583207963577L;
+
+ /**
+ * Constructs a new <code>NotCompliantMBeanException</code>.
+ */
+ public NotCompliantMBeanException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>NotCompliantMBeanException</code>
+ * with the specified message.
+ *
+ * @param message the error message to give to the user.
+ */
+ public NotCompliantMBeanException(String message)
+ {
+ super(message);
+ }
+
+}
+
diff --git a/javax/management/Notification.java b/javax/management/Notification.java
new file mode 100644
index 000000000..52c11de06
--- /dev/null
+++ b/javax/management/Notification.java
@@ -0,0 +1,314 @@
+/* Notification.java -- A notification emitted by a bean.
+ 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 javax.management;
+
+import java.util.Date;
+import java.util.EventObject;
+
+/**
+ * <p>
+ * A notification message that may be emitted by a bean.
+ * Notifications have both a message and a type, so individual
+ * notifications can be grouped by type. They also incorporate
+ * sequencing, so that the recipient can order the delivered
+ * messages correctly (there is no guarantee that they will
+ * be delivered in order).
+ * </p>
+ * <p>
+ * Notifications also include a reference to the source of
+ * the notification. The source bean is represented either
+ * by an {@link ObjectName} or by a direct reference to the
+ * bean. The former is preferable, and notifications emitted
+ * via a {@link MBeanServer} will automatically have the source
+ * transformed into an {@link ObjectName}.
+ * </p>
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class Notification
+ extends EventObject
+{
+
+ /**
+ * The notification message.
+ *
+ * @serial the notification message.
+ */
+ private String message;
+
+ /**
+ * The notification's sequence number, relative to the notifications
+ * emitted by the bean.
+ *
+ * @serial the notification sequence number.
+ */
+ private long sequenceNumber;
+
+ /**
+ * The source of the notification. This is redeclared in order to
+ * replace the <code>source</code> variable in {@link java.util.EventObject}
+ * with a non-transient version.
+ *
+ * @serial the notification source.
+ */
+ protected Object source;
+
+ /**
+ * The time the notification was generated.
+ *
+ * @serial the notification timestamp.
+ */
+ private long timeStamp;
+
+ /**
+ * The type of notification sent. This utilises the same style
+ * as Java property and package names. For example,
+ * <code>gnu.gcj.compiler</code> may be one type of notifications.
+ *
+ * @serial the notification type.
+ */
+ private String type;
+
+ /**
+ * The user data associated with the notification. This includes
+ * any additional data which should be transmitted with the notification,
+ * but can't be achieved using the {@link java.lang.String} format
+ * of the <code>message</code>.
+ *
+ * @serial the notification user data.
+ */
+ private Object userData;
+
+ /**
+ * Creates a new {@link Notification} object with the specified type,
+ * source and sequence number. The timestamp is created using the
+ * current date and time.
+ *
+ * @param type the type of the notification.
+ * @param source the source of the notification.
+ * @param sequenceNumber the sequence number of the notifcation.
+ */
+ public Notification(String type, Object source, long sequenceNumber)
+ {
+ this(type, source, sequenceNumber, new Date().getTime());
+ }
+
+ /**
+ * Creates a new {@link Notification} object with the specified type,
+ * source, sequence number and timestamp.
+ *
+ * @param type the type of the notification.
+ * @param source the source of the notification.
+ * @param sequenceNumber the sequence number of the notifcation.
+ * @param timeStamp the time the notification was emitted.
+ */
+ public Notification(String type, Object source, long sequenceNumber,
+ long timeStamp)
+ {
+ this(type, source, sequenceNumber, timeStamp, null);
+ }
+
+ /**
+ * Creates a new {@link Notification} object with the specified type,
+ * source, sequence number, timestamp and message.
+ *
+ * @param type the type of the notification.
+ * @param source the source of the notification.
+ * @param sequenceNumber the sequence number of the notifcation.
+ * @param timeStamp the time the notification was emitted.
+ * @param message the message contained in the notification.
+ */
+ public Notification(String type, Object source, long sequenceNumber,
+ long timeStamp, String message)
+ {
+ super(source);
+ this.type = type;
+ this.sequenceNumber = sequenceNumber;
+ this.timeStamp = timeStamp;
+ this.message = message;
+ }
+
+ /**
+ * Creates a new {@link Notification} object with the specified type,
+ * source, sequence number and message. The timestamp is created using
+ * the current date and time.
+ *
+ * @param type the type of the notification.
+ * @param source the source of the notification.
+ * @param sequenceNumber the sequence number of the notifcation.
+ * @param message the message contained in the notification.
+ */
+ public Notification(String type, Object source, long sequenceNumber,
+ String message)
+ {
+ this(type, source, sequenceNumber, new Date().getTime(), message);
+ }
+
+ /**
+ * Returns the message contained in this notification. The message
+ * is in {@link java.lang.String} form, and is thus intended for
+ * display to the end-user. Data transferred as part of the notification
+ * which shouldn't be displayed is included in the <code>userData</code>
+ * field.
+ *
+ * @return the notification message.
+ * @see #getUserData()
+ * @see #setUserData(java.lang.Object)
+ */
+ public String getMessage()
+ {
+ return message;
+ }
+
+ /**
+ * Returns the sequence number of this notification. This
+ * can be used to determine the order in which notifications
+ * were emitted by the broadcasting bean.
+ *
+ * @return the sequence number.
+ * @see #setSequenceNumber(long)
+ */
+ public long getSequenceNumber()
+ {
+ return sequenceNumber;
+ }
+
+ /**
+ * Returns the date and time at which this notification was
+ * emitted.
+ *
+ * @return the notification timestamp.
+ * @see #setTimeStamp(long)
+ */
+ public long getTimeStamp()
+ {
+ return timeStamp;
+ }
+
+ /**
+ * Returns the type of this notification. Types take the same
+ * form as Java package and property names.
+ *
+ * @return the type of the notification.
+ */
+ public String getType()
+ {
+ return type;
+ }
+
+ /**
+ * Returns the additional user data associated with the notification.
+ * This is used to attach additional non-textual information to the
+ * notification.
+ *
+ * @return the user data associated with the notification.
+ * @see #setUserData(java.lang.Object)
+ */
+ public Object getUserData()
+ {
+ return userData;
+ }
+
+ /**
+ * Sets the sequence number to the value specified.
+ *
+ * @param sequenceNumber the new sequence number.
+ * @see #getSequenceNumber()
+ */
+ public void setSequenceNumber(long sequenceNumber)
+ {
+ this.sequenceNumber = sequenceNumber;
+ }
+
+ /**
+ * Sets the source of this notification to the value
+ * specified.
+ *
+ * @param source the new source of the notification.
+ * @see java.util.EventSource#getSource()
+ */
+ public void setSource(Object source)
+ {
+ this.source = source;
+ }
+
+ /**
+ * Sets the date and time at which this notification
+ * was emitted.
+ *
+ * @param timeStamp the new time stamp of the notification.
+ * @see #getTimeStamp()
+ */
+ public void setTimeStamp(long timeStamp)
+ {
+ this.timeStamp = timeStamp;
+ }
+
+ /**
+ * Sets the additional user data associated with the notification
+ * to the specified value. This is used to attach additional
+ * non-textual information to the notification.
+ *
+ * @param userData the new user data associated with the notification.
+ * @see #getUserData()
+ */
+ public void setUserData(Object userData)
+ {
+ this.userData = userData;
+ }
+
+ /**
+ * A textual representation of the notification.
+ *
+ * @return the notification in {@link java.lang.String} form.
+ */
+ public String toString()
+ {
+ return getClass().getName()
+ + "[message=" + message
+ + ", sequenceNumber=" + sequenceNumber
+ + ", source=" + source
+ + ", timeStamp=" + timeStamp
+ + ", type=" + type
+ + ", userData=" + userData
+ + "]";
+ }
+
+}
+
diff --git a/javax/management/NotificationBroadcaster.java b/javax/management/NotificationBroadcaster.java
new file mode 100644
index 000000000..139d842bb
--- /dev/null
+++ b/javax/management/NotificationBroadcaster.java
@@ -0,0 +1,112 @@
+/* NotificationBroadcaster.java -- Interface for broadcasters.
+ 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 javax.management;
+
+/**
+ * <p>
+ * Represents a bean that can emit notifications when
+ * events occur. Other beans can use this interface
+ * to add themselves to the list of recipients of such
+ * notifications.
+ * </p>
+ * <p>
+ * <strong>Note</strong>: New classes should use
+ * {@link NotificationEmitter}, a subinterface of this,
+ * in preference to using this interface directly.
+ * </p>
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface NotificationBroadcaster
+{
+
+ /**
+ * Registers the specified listener as a new recipient of
+ * notifications from this bean. If non-null, the filter
+ * argument will be used to select which notifications are
+ * delivered. The supplied object will also be passed to
+ * the recipient with each notification. This should not
+ * be modified by the broadcaster, but instead should be
+ * passed unmodified to the listener.
+ *
+ * @param listener the new listener, who will receive
+ * notifications from this broadcasting bean.
+ * @param filter a filter to determine which notifications are
+ * delivered to the listener, or <code>null</code>
+ * if no filtering is required.
+ * @param passback an object to be passed to the listener with
+ * each notification.
+ * @throws IllegalArgumentException if <code>listener</code> is
+ * <code>null</code>.
+ * @see #removeNotificationListener(NotificationListener)
+ */
+ void addNotificationListener(NotificationListener listener,
+ NotificationFilter filter,
+ Object passback)
+ throws IllegalArgumentException;
+
+ /**
+ * Returns an array describing the notifications this
+ * bean may send to its registered listeners. Ideally, this
+ * array should be complete, but in some cases, this may
+ * not be possible. However, be aware that some listeners
+ * may expect this to be so.
+ *
+ * @return the array of possible notifications.
+ */
+ MBeanNotificationInfo[] getNotificationInfo();
+
+ /**
+ * Removes the specified listener from the list of recipients
+ * of notifications from this bean. This includes all combinations
+ * of filters and passback objects registered for this listener.
+ * For more specific removal of listeners, see the subinterface
+ * {@link NotificationEmitter}.
+ *
+ * @param listener the listener to remove.
+ * @throws ListenerNotFoundException if the specified listener
+ * is not registered with this bean.
+ * @see #addNotificationListener(NotificationListener, NotificationFilter,
+ * java.lang.Object)
+ */
+ void removeNotificationListener(NotificationListener listener)
+ throws ListenerNotFoundException;
+
+}
+
diff --git a/javax/management/NotificationEmitter.java b/javax/management/NotificationEmitter.java
new file mode 100644
index 000000000..002e2fe18
--- /dev/null
+++ b/javax/management/NotificationEmitter.java
@@ -0,0 +1,76 @@
+/* NotificationEmitter.java -- Refined interface for broadcasters.
+ 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 javax.management;
+
+/**
+ * Represents a bean that can emit notifications when
+ * events occur. Other beans can use this interface
+ * to add themselves to the list of recipients of such
+ * notifications.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface NotificationEmitter
+ extends NotificationBroadcaster
+{
+
+ /**
+ * Removes the specified listener from the list of recipients
+ * of notifications from this bean. Only the first instance with
+ * the supplied filter and passback object is removed.
+ * <code>null</code> is used as a valid value for these parameters,
+ * rather than as a way to remove all registration instances for
+ * the specified listener; for this behaviour instead, see the details
+ * of the same method in {@link NotificationBroadcaster}.
+ *
+ * @param listener the listener to remove.
+ * @param filter the filter of the listener to remove.
+ * @param passback the passback object of the listener to remove.
+ * @throws ListenerNotFoundException if the specified listener
+ * is not registered with this bean.
+ * @see #addNotificationListener(NotificationListener, NotificationFilter,
+ * java.lang.Object)
+ */
+ void removeNotificationListener(NotificationListener listener,
+ NotificationFilter filter,
+ Object passback)
+ throws ListenerNotFoundException;
+
+}
+
diff --git a/javax/management/NotificationFilter.java b/javax/management/NotificationFilter.java
new file mode 100644
index 000000000..a8e41c93f
--- /dev/null
+++ b/javax/management/NotificationFilter.java
@@ -0,0 +1,66 @@
+/* NotificationFilter.java -- Interface for notification filters.
+ 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 javax.management;
+
+import java.io.Serializable;
+
+/**
+ * Represents a object that acts as a filter for notifications.
+ * Implementations of this class are used to determine which
+ * notifications should be passed to a receiving bean, and which
+ * should not.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface NotificationFilter
+ extends Serializable
+{
+
+ /**
+ * Returns true if the specified notification should be passed
+ * on to the listener.
+ *
+ * @param notification the notification being delivered.
+ * @return true if the notification should be passed to the
+ * listener, false otherwise.
+ */
+ boolean isNotificationEnabled(Notification notification);
+
+}
+
diff --git a/javax/management/NotificationListener.java b/javax/management/NotificationListener.java
new file mode 100644
index 000000000..69b08eee3
--- /dev/null
+++ b/javax/management/NotificationListener.java
@@ -0,0 +1,70 @@
+/* NotificationListener.java -- Interface for receivers of notifications.
+ 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 javax.management;
+
+import java.util.EventListener;
+
+/**
+ * Represents a object that can receive notifications from
+ * a bean.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface NotificationListener
+ extends EventListener
+{
+
+ /**
+ * Invoked by the notifying bean when a notification is to
+ * be delivered to the recipient. As the transmission of
+ * notifications takes place sequentially, implementors of
+ * this method should avoid performing lengthy operations,
+ * as the notifying bean will stall until the method is
+ * complete.
+ *
+ * @param notification the notification from the bean.
+ * @param passback the object that was passed to the notifying
+ * bean as part of the registration process.
+ * @see NotificationBroadcaster#addListener(NotificationListener,
+ * NotificationFilter, Object)
+ */
+ void handleNotification(Notification notification, Object passback);
+
+}
+
diff --git a/javax/management/OperationsException.java b/javax/management/OperationsException.java
index 33be4bb01..cbd90d637 100644
--- a/javax/management/OperationsException.java
+++ b/javax/management/OperationsException.java
@@ -49,6 +49,11 @@ public class OperationsException
{
/**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -4967597595580536216L;
+
+ /**
* Constructs a new <code>OperationsException</code>.
*/
public OperationsException()
diff --git a/javax/management/RuntimeErrorException.java b/javax/management/RuntimeErrorException.java
new file mode 100644
index 000000000..811dc40f2
--- /dev/null
+++ b/javax/management/RuntimeErrorException.java
@@ -0,0 +1,115 @@
+/* RuntimeErrorException.java -- A user-defined management error.
+ 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 javax.management;
+
+/**
+ * Represents an arbitrary error thrown by a management
+ * bean. When a management bean executes code that causes
+ * an error to be thrown, the resulting error is
+ * wrapped inside an {@link RuntimeErrorException}. Calling
+ * {@link getTargetError()} will return the wrapped
+ * exception.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class RuntimeErrorException
+ extends JMRuntimeException
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 704338937753949796L;
+
+ /**
+ * The target error.
+ *
+ * @serial the target error.
+ */
+ private Error error;
+
+ /**
+ * Constructs a new <code>RuntimeErrorException</code> wrapping
+ * the specified error.
+ *
+ * @param e the error to be wrapped.
+ */
+ public RuntimeErrorException(Error e)
+ {
+ super();
+ error = e;
+ }
+
+ /**
+ * Constructs a new <code>RuntimeErrorException</code> wrapping
+ * the specified error and using the supplied message.
+ *
+ * @param e the error to be wrapped.
+ * @param message the error message to give to the user.
+ */
+ public RuntimeErrorException(Error e, String message)
+ {
+ super(message);
+ error = e;
+ }
+
+ /**
+ * Returns the true cause of this error, the wrapped
+ * error.
+ *
+ * @return the wrapped error.
+ */
+ public Throwable getCause()
+ {
+ return error;
+ }
+
+ /**
+ * Returns the true cause of this error, the wrapped
+ * error.
+ *
+ * @return the wrapped error.
+ */
+ public Error getTargetError()
+ {
+ return error;
+ }
+
+}
+
diff --git a/javax/management/RuntimeMBeanException.java b/javax/management/RuntimeMBeanException.java
new file mode 100644
index 000000000..95225a80a
--- /dev/null
+++ b/javax/management/RuntimeMBeanException.java
@@ -0,0 +1,114 @@
+/* RuntimeMBeanException.java -- A user-defined management exception.
+ 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 javax.management;
+
+/**
+ * Represents an arbitrary runtime exception thrown by a management
+ * bean. When a management bean executes code that causes a runtime
+ * exception to be thrown, the resulting exception is wrapped inside a
+ * {@link RuntimeMBeanException}. Calling {@link
+ * getTargetException()} will return the wrapped exception.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class RuntimeMBeanException
+ extends JMRuntimeException
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 5274912751982730171L;
+
+ /**
+ * The target exception.
+ *
+ * @serial the target exception.
+ */
+ private RuntimeException runtimeException;
+
+ /**
+ * Constructs a new <code>RuntimeMBeanException</code> wrapping
+ * the specified exception.
+ *
+ * @param e the exception to be wrapped.
+ */
+ public RuntimeMBeanException(RuntimeException e)
+ {
+ super();
+ runtimeException = e;
+ }
+
+ /**
+ * Constructs a new <code>RuntimeMBeanException</code> wrapping
+ * the specified exception and using the supplied message.
+ *
+ * @param e the exception to be wrapped.
+ * @param message the error message to give to the user.
+ */
+ public RuntimeMBeanException(RuntimeException e, String message)
+ {
+ super(message);
+ runtimeException = e;
+ }
+
+ /**
+ * Returns the true cause of this exception, the wrapped runtime
+ * exception.
+ *
+ * @return the wrapped exception.
+ */
+ public Throwable getCause()
+ {
+ return runtimeException;
+ }
+
+ /**
+ * Returns the true cause of this exception, the wrapped runtime
+ * exception.
+ *
+ * @return the wrapped exception.
+ */
+ public RuntimeException getTargetException()
+ {
+ return runtimeException;
+ }
+
+}
+
diff --git a/javax/management/ServiceNotFoundException.java b/javax/management/ServiceNotFoundException.java
new file mode 100644
index 000000000..602e1490d
--- /dev/null
+++ b/javax/management/ServiceNotFoundException.java
@@ -0,0 +1,75 @@
+/* ServiceNotFoundException.java -- Thrown by invalid values.
+ 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 javax.management;
+
+/**
+ * Thrown when a requested service is unsupported.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class ServiceNotFoundException
+ extends OperationsException
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -3990675661956646827L;
+
+ /**
+ * Constructs a new <code>ServiceNotFoundException</code>.
+ */
+ public ServiceNotFoundException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>ServiceNotFoundException</code>
+ * with the specified message.
+ *
+ * @param message the error message to give to the user.
+ */
+ public ServiceNotFoundException(String message)
+ {
+ super(message);
+ }
+
+}
+
diff --git a/javax/management/StandardMBean.java b/javax/management/StandardMBean.java
new file mode 100644
index 000000000..16b6f0b66
--- /dev/null
+++ b/javax/management/StandardMBean.java
@@ -0,0 +1,921 @@
+/* StandardMBean.java -- A standard reflection-based management bean.
+ 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 javax.management;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Provides a dynamic management bean by using reflection on an
+ * interface and an implementing class. By default, a bean instance
+ * is paired up with its interface based on specific naming
+ * conventions (if the implementation is called X, the interface must
+ * be XMBean). Using this class removes the need to use a specific
+ * naming system to match up the two. Instead, an instance of this
+ * bean is created either via explicit construction or subclassing,
+ * and this provides access to the attributes, constructors and
+ * operations of the implementation via reflection. Various hooks are
+ * provided in order to allow customization of this process.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class StandardMBean
+ implements DynamicMBean
+{
+
+ /**
+ * The interface for this bean.
+ */
+ private Class iface;
+
+ /**
+ * The implementation of the interface.
+ */
+ private Object impl;
+
+ /**
+ * Cached bean information.
+ */
+ private MBeanInfo info;
+
+ /**
+ * Constructs a new {@link StandardMBean} using the specified
+ * interface and <code>this</code> as the instance. This should
+ * be used to create an instance via subclassing.
+ *
+ * @param iface the interface this bean implements, or <code>null</code>
+ * if the interface should be determined using the naming
+ * convention (class X has interface XMBean).
+ * @throws NotCompliantMBeanException if this class doesn't implement
+ * the interface or a method appears
+ * in the interface that doesn't comply
+ * with the naming conventions.
+ */
+ protected StandardMBean(Class iface)
+ throws NotCompliantMBeanException
+ {
+ if (iface == null)
+ {
+ String className = getClass().getName();
+ try
+ {
+ iface = Class.forName(className + "MBean");
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw (NotCompliantMBeanException)
+ (new NotCompliantMBeanException("An interface for the class " +
+ className + " was not found.").initCause(e));
+ }
+ }
+ if (!(iface.isInstance(this)))
+ throw new NotCompliantMBeanException("The instance, " + impl +
+ ", is not an instance of " + iface);
+ impl = this;
+ this.iface = iface;
+ }
+
+ /**
+ * Constructs a new {@link StandardMBean} using the specified
+ * interface and the supplied instance as the implementation.
+ *
+ * @param impl the implementation.
+ * @param iface the interface the bean implements, or <code>null</code>
+ * if the interface should be determined using the naming
+ * convention (class X has interface XMBean).
+ * @throws IllegalArgumentException if <code>impl</code> is <code>null</code>.
+ * @throws NotCompliantMBeanException if <code>impl</code> doesn't implement
+ * the interface or a method appears
+ * in the interface that doesn't comply
+ * with the naming conventions.
+ */
+ public StandardMBean(Object impl, Class iface)
+ throws NotCompliantMBeanException
+ {
+ if (impl == null)
+ throw new IllegalArgumentException("The specified implementation is null.");
+ if (iface == null)
+ {
+ String className = impl.getClass().getName();
+ try
+ {
+ iface = Class.forName(className + "MBean");
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw (NotCompliantMBeanException)
+ (new NotCompliantMBeanException("An interface for the class " +
+ className + " was not found.").initCause(e));
+ }
+ }
+ if (!(iface.isInstance(impl)))
+ throw new NotCompliantMBeanException("The instance, " + impl +
+ ", is not an instance of " + iface);
+ this.impl = impl;
+ this.iface = iface;
+ }
+
+ /**
+ * Caches the {@link MBeanInfo} instance for this object. This is a
+ * customization hook, so that subclasses can choose the caching policy
+ * used. The default implementation caches the value in the instance
+ * itself. Subclasses may override this so as to not cache the data
+ * at all, or so as to use a cache shared between multiple beans.
+ *
+ * @param info the {@link MBeanInfo} instance to cache, or <code>null</code>
+ * if there is no new value to cache. When the value is not
+ * <code>null</code>, the cache should replace the current value
+ * with the value supplied here.
+ * @see #getCachedMBeanInfo()
+ */
+ protected void cacheMBeanInfo(MBeanInfo info)
+ {
+ if (info != null)
+ this.info = info;
+ }
+
+ /**
+ * Obtains the value of the specified attribute of the
+ * management bean. The management bean should perform
+ * a lookup for the named attribute, and return its value
+ * by calling the appropriate getter method, if possible.
+ *
+ * @param name the name of the attribute to retrieve.
+ * @return the value of the specified attribute.
+ * @throws AttributeNotFoundException if the name does not
+ * correspond to an attribute
+ * of the bean.
+ * @throws MBeanException if retrieving the attribute causes
+ * the bean to throw an exception (which
+ * becomes the cause of this exception).
+ * @throws ReflectionException if an exception occurred in trying
+ * to use the reflection interface
+ * to lookup the attribute. The
+ * thrown exception is the cause of
+ * this exception.
+ * @see #setAttribute(String)
+ */
+ public Object getAttribute(String name)
+ throws AttributeNotFoundException, MBeanException,
+ ReflectionException
+ {
+ Method getter;
+ try
+ {
+ getter = iface.getMethod("get" + name, null);
+ }
+ catch (NoSuchMethodException e)
+ {
+ try
+ {
+ getter = iface.getMethod("is" + name, null);
+ }
+ catch (NoSuchMethodException ex)
+ {
+ throw ((AttributeNotFoundException)
+ new AttributeNotFoundException("The attribute, " + name +
+ ", was not found.").initCause(ex));
+ }
+ }
+ Object result;
+ try
+ {
+ result = getter.invoke(impl, null);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new ReflectionException(e, "Failed to retrieve " + name);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ReflectionException(e, "Failed to retrieve " + name);
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new MBeanException((Exception) e.getCause(),
+ "The getter of " + name +
+ " threw an exception");
+ }
+ return result;
+ }
+
+ /**
+ * Obtains the values of each of the specified attributes
+ * of the management bean. The returned list includes
+ * those attributes that were retrieved and their
+ * corresponding values.
+ *
+ * @param names the names of the attributes to retrieve.
+ * @return a list of the retrieved attributes.
+ * @see #setAttributes(AttributeList)
+ */
+ public AttributeList getAttributes(String[] names)
+ {
+ AttributeList list = new AttributeList(names.length);
+ for (int a = 0; a < names.length; ++a)
+ {
+ try
+ {
+ Object value = getAttribute(names[a]);
+ list.add(new Attribute(names[a], value));
+ }
+ catch (AttributeNotFoundException e)
+ {
+ /* Ignored */
+ }
+ catch (ReflectionException e)
+ {
+ /* Ignored */
+ }
+ catch (MBeanException e)
+ {
+ /* Ignored */
+ }
+ }
+ return list;
+ }
+
+ /**
+ * Returns the cached {@link MBeanInfo} instance for this object. This is a
+ * customization hook, so that subclasses can choose the caching policy
+ * used. The default implementation caches the value in the instance
+ * itself, and returns this value on calls to this method.
+ *
+ * @return the cached {@link MBeanInfo} instance, or <code>null</code>
+ * if no value is cached.
+ * @see #cacheMBeanInfo(javax.management.MBeanInfo)
+ */
+ protected MBeanInfo getCachedMBeanInfo()
+ {
+ return info;
+ }
+
+ /**
+ * Returns the class name that will be used in the {@link MBeanInfo}
+ * instance. This is a customization hook, so that subclasses can
+ * provide a custom class name. By default, this returns the class
+ * name from the supplied {@link MBeanInfo} instance.
+ *
+ * @param info the {@link MBeanInfo} instance constructed via
+ * reflection.
+ * @return the class name to use in the instance.
+ */
+ protected String getClassName(MBeanInfo info)
+ {
+ return info.getClassName();
+ }
+
+ /**
+ * Returns information on the constructors that will be used in
+ * the {@link MBeanInfo} instance. This is a customization hook,
+ * so that subclasses can provide their own information on the
+ * bean's constructors, if necessary. By default, this method
+ * returns <code>null</code> unless the implementation supplied
+ * is either <code>null</code> or <code>this</code>. This default
+ * implementation prevents the use of
+ * {@link MBeanServer#createMBean} in cases where the bean is
+ * not created as a subclass of {@link StandardMBean}.
+ *
+ * @param constructors the constructor information created via
+ * reflection.
+ * @param impl the implementation, or <code>null</code> if this
+ * should be ignored.
+ * @return the constructor information to use.
+ */
+ protected MBeanConstructorInfo[] getConstructors(MBeanConstructorInfo[]
+ constructors, Object impl)
+ {
+ if (impl == null || impl == this)
+ return constructors;
+ return null;
+ }
+
+ /**
+ * Returns the description of the attribute that will be used in
+ * the supplied {@link MBeanAttributeInfo} instance. This is a
+ * customization hook, so that subclasses can provide a custom
+ * description. By default, this calls
+ * {@link #getDescription(MBeanFeatureInfo)} with the supplied
+ * {@link MBeanAttributeInfo} instance.
+ *
+ * @param info the {@link MBeanAttributeInfo} instance constructed
+ * via reflection.
+ * @return the description to use in the instance.
+ */
+ protected String getDescription(MBeanAttributeInfo info)
+ {
+ return getDescription((MBeanFeatureInfo) info);
+ }
+
+ /**
+ * Returns the description of the constructor that will be used in
+ * the supplied {@link MBeanConstructorInfo} instance. This is a
+ * customization hook, so that subclasses can provide a custom
+ * description. By default, this calls
+ * {@link #getDescription(MBeanFeatureInfo)} with the supplied
+ * {@link MBeanConstructorInfo} instance.
+ *
+ * @param info the {@link MBeanConstructorInfo} instance constructed
+ * via reflection.
+ * @return the description to use in the instance.
+ */
+ protected String getDescription(MBeanConstructorInfo info)
+ {
+ return getDescription((MBeanFeatureInfo) info);
+ }
+
+ /**
+ * Returns the description of the nth parameter of the constructor
+ * that will be used in the supplied {@link MBeanParameterInfo}
+ * instance. This is a customization hook, so that subclasses
+ * can provide a custom description. By default, this calls
+ * <code>param.getDescription()</code>.
+ *
+ * @param info the {@link MBeanConstructorInfo} instance constructed
+ * via reflection.
+ * @param param the {@link MBeanParameterInfo} instance constructed
+ * via reflection.
+ * @param n the number of the parameter, in order to link it to the
+ * information on the constructor.
+ * @return the description to use in the instance.
+ */
+ protected String getDescription(MBeanConstructorInfo info,
+ MBeanParameterInfo param, int n)
+ {
+ return param.getDescription();
+ }
+
+ /**
+ * Returns the description of the supplied feature that
+ * will be used in the supplied {@link MBeanFeatureInfo}
+ * instance. This is a customization hook, so that subclasses
+ * can provide a custom description. By default, this calls
+ * <code>info.getDescription()</code>. This method is also called
+ * by default for the more specific description methods for attributes,
+ * constructors and operations.
+ *
+ * @param info the {@link MBeanFeatureInfo} instance constructed
+ * via reflection.
+ * @return the description to use in the instance.
+ */
+ protected String getDescription(MBeanFeatureInfo info)
+ {
+ return info.getDescription();
+ }
+
+ /**
+ * Returns the description of the bean that will be used in the
+ * supplied {@link MBeanInfo} instance. This is a customization
+ * hook, so that subclasses can provide a custom description. By
+ * default, this calls <code>info.getDescription()</code>.
+ *
+ * @param info the {@link MBeanInfo} instance constructed
+ * via reflection.
+ * @return the description to use in the instance.
+ */
+ protected String getDescription(MBeanInfo info)
+ {
+ return info.getDescription();
+ }
+
+ /**
+ * Returns the description of the operation that will be used in
+ * the supplied {@link MBeanOperationInfo} instance. This is a
+ * customization hook, so that subclasses can provide a custom
+ * description. By default, this calls
+ * {@link #getDescription(MBeanFeatureInfo)} with the supplied
+ * {@link MBeanOperationInfo} instance.
+ *
+ * @param info the {@link MBeanOperationInfo} instance constructed
+ * via reflection.
+ * @return the description to use in the instance.
+ */
+ protected String getDescription(MBeanOperationInfo info)
+ {
+ return getDescription((MBeanFeatureInfo) info);
+ }
+
+ /**
+ * Returns the description of the nth parameter of the operation
+ * that will be used in the supplied {@link MBeanParameterInfo}
+ * instance. This is a customization hook, so that subclasses
+ * can provide a custom description. By default, this calls
+ * <code>param.getDescription()</code>.
+ *
+ * @param info the {@link MBeanOperationInfo} instance constructed
+ * via reflection.
+ * @param param the {@link MBeanParameterInfo} instance constructed
+ * via reflection.
+ * @param n the number of the parameter, in order to link it to the
+ * information on the operation.
+ * @return the description to use in the instance.
+ */
+ protected String getDescription(MBeanOperationInfo info,
+ MBeanParameterInfo param, int n)
+ {
+ return param.getDescription();
+ }
+
+ /**
+ * Returns the impact of the operation that will be used in the
+ * supplied {@link MBeanOperationInfo} instance. This is a
+ * customization hook, so that subclasses can provide a custom
+ * impact flag. By default, this returns
+ * <code>info.getImpact()</code>.
+ *
+ * @param info the {@link MBeanOperationInfo} instance constructed
+ * via reflection.
+ * @return the impact flag to use in the instance.
+ */
+ protected int getImpact(MBeanOperationInfo info)
+ {
+ return info.getImpact();
+ }
+
+ /**
+ * Returns the instance that implements this bean.
+ *
+ * @return the implementation.
+ */
+ public Object getImplementation()
+ {
+ return impl;
+ }
+
+ /**
+ * Returns the class of the instance that implements this bean.
+ *
+ * @return the implementation class.
+ */
+ public Class getImplementationClass()
+ {
+ return impl.getClass();
+ }
+
+ /**
+ * <p>
+ * Returns an information object which lists the attributes
+ * and actions associated with the management bean. This
+ * implementation proceeds as follows:
+ * </p>
+ * <ol>
+ * <li>{@link #getCachedMBeanInfo()} is called to obtain
+ * the cached instance. If this returns a non-null value,
+ * this value is returned.</li>
+ * <li>If there is no cached value, then the method proceeds
+ * to create one. During this process, the customization hooks
+ * detailed in this class are called to allow the values used
+ * to be overrided:
+ * <ul>
+ * <li>For each attribute,
+ * {@link #getDescription(MBeanAttributeInfo)} is called.</li>
+ * <li>For each constructor,
+ * {@link #getDescription(MBeanConstructorInfo)} is called,
+ * along with {@link #getDescription(MBeanConstructorInfo,
+ * MBeanParameterInfo, int)} and
+ * {@link #getParameterName(MBeanConstructorInfo,
+ * MBeanParameterInfo, int)} for each parameter.</li>
+ * <li>The constructors may be replaced as a whole by
+ * a call to
+ * {@link #getConstructors(MBeanConstructorInfo[], Object)}.</li>
+ * <li>For each operation,
+ * {@link #getDescription(MBeanOperationInfo)} and
+ * {@link #getImpact(MBeanOperationInfo)} are called,
+ * along with {@link #getDescription(MBeanOperationInfo,
+ * MBeanParameterInfo, int)} and
+ * {@link #getParameterName(MBeanOperationInfo,
+ * MBeanParameterInfo, int)} for each parameter.</li>
+ * <li>{@link #getClassName(MBeanInfo)} and
+ * {@link #getDescription(MBeanInfo)} are called to customise
+ * the basic information about the class.</li>
+ * </ul>
+ * </li>
+ * <li>Finally, {@link #cacheMBeanInfo(MBeanInfo)} is called
+ * with the created instance before it is returned.</li>
+ * </ol>
+ *
+ * @return a description of the management bean, including
+ * all exposed attributes and actions.
+ */
+ public MBeanInfo getMBeanInfo()
+ {
+ MBeanInfo info = getCachedMBeanInfo();
+ if (info != null)
+ return info;
+ Method[] methods = iface.getMethods();
+ Map attributes = new HashMap();
+ List operations = new ArrayList();
+ for (int a = 0; a < methods.length; ++a)
+ {
+ String name = methods[a].getName();
+ if (((name.startsWith("get") &&
+ methods[a].getReturnType() != Void.TYPE) ||
+ (name.startsWith("is") &&
+ methods[a].getReturnType() == Boolean.TYPE)) &&
+ methods[a].getParameterTypes().length == 0)
+ {
+ Method[] amethods;
+ String attrib;
+ if (name.startsWith("is"))
+ attrib = name.substring(2);
+ else
+ attrib = name.substring(3);
+ if (attributes.containsKey(attrib))
+ amethods = (Method[]) attributes.get(attrib);
+ else
+ {
+ amethods = new Method[2];
+ attributes.put(attrib, amethods);
+ }
+ amethods[0] = methods[a];
+ }
+ else if (name.startsWith("set") &&
+ methods[a].getReturnType() == Void.TYPE &&
+ methods[a].getParameterTypes().length == 1)
+ {
+ Method[] amethods;
+ String attrib = name.substring(3);
+ if (attributes.containsKey(attrib))
+ amethods = (Method[]) attributes.get(attrib);
+ else
+ {
+ amethods = new Method[2];
+ attributes.put(attrib, amethods);
+ }
+ amethods[1] = methods[a];
+ }
+ else
+ operations.add(new MBeanOperationInfo(methods[a].getName(),
+ methods[a]));
+ }
+ List attribs = new ArrayList(attributes.size());
+ Iterator it = attributes.entrySet().iterator();
+ while (it.hasNext())
+ {
+ Map.Entry entry = (Map.Entry) it.next();
+ Method[] amethods = (Method[]) entry.getValue();
+ try
+ {
+ attribs.add(new MBeanAttributeInfo((String) entry.getKey(),
+ (String) entry.getKey(),
+ amethods[0], amethods[1]));
+ }
+ catch (IntrospectionException e)
+ {
+ /* Shouldn't happen; both shouldn't be null */
+ throw new IllegalStateException("The two methods passed to " +
+ "the MBeanAttributeInfo " +
+ "constructor for " + entry +
+ "were null.", e);
+ }
+ }
+ MBeanAttributeInfo[] ainfo = new MBeanAttributeInfo[attribs.size()];
+ for (int a = 0; a < ainfo.length; ++a)
+ {
+ MBeanAttributeInfo oldInfo = (MBeanAttributeInfo) attribs.get(a);
+ String desc = getDescription(oldInfo);
+ ainfo[a] = new MBeanAttributeInfo(oldInfo.getName(),
+ oldInfo.getType(), desc,
+ oldInfo.isReadable(),
+ oldInfo.isWritable(),
+ oldInfo.isIs());
+ }
+ Constructor[] cons = impl.getClass().getConstructors();
+ MBeanConstructorInfo[] cinfo = new MBeanConstructorInfo[cons.length];
+ for (int a = 0; a < cinfo.length; ++a)
+ {
+ MBeanConstructorInfo oldInfo = new MBeanConstructorInfo(cons[a].getName(),
+ cons[a]);
+ String desc = getDescription(oldInfo);
+ MBeanParameterInfo[] params = oldInfo.getSignature();
+ MBeanParameterInfo[] pinfo = new MBeanParameterInfo[params.length];
+ for (int b = 0; b < pinfo.length; ++b)
+ {
+ String pdesc = getDescription(oldInfo, params[b], b);
+ String pname = getParameterName(oldInfo, params[b], b);
+ pinfo[b] = new MBeanParameterInfo(pname, params[b].getType(),
+ pdesc);
+ }
+ cinfo[a] = new MBeanConstructorInfo(oldInfo.getName(), desc,
+ pinfo);
+ }
+ cinfo = getConstructors(cinfo, impl);
+ MBeanOperationInfo[] oinfo = new MBeanOperationInfo[operations.size()];
+ for (int a = 0; a < oinfo.length; ++a)
+ {
+ MBeanOperationInfo oldInfo = (MBeanOperationInfo) operations.get(a);
+ String desc = getDescription(oldInfo);
+ int impact = getImpact(oldInfo);
+ MBeanParameterInfo[] params = oldInfo.getSignature();
+ MBeanParameterInfo[] pinfo = new MBeanParameterInfo[params.length];
+ for (int b = 0; b < pinfo.length; ++b)
+ {
+ String pdesc = getDescription(oldInfo, params[b], b);
+ String pname = getParameterName(oldInfo, params[b], b);
+ pinfo[b] = new MBeanParameterInfo(pname, params[b].getType(),
+ pdesc);
+ }
+ oinfo[a] = new MBeanOperationInfo(oldInfo.getName(), desc, pinfo,
+ oldInfo.getReturnType(), impact);
+ }
+ info = new MBeanInfo(impl.getClass().getName(), impl.getClass().getName(),
+ ainfo, cinfo, oinfo, null);
+ String cname = getClassName(info);
+ String desc = getDescription(info);
+ info = new MBeanInfo(cname, desc, ainfo, cinfo, oinfo, null);
+ cacheMBeanInfo(info);
+ return info;
+ }
+
+ /**
+ * Returns the interface for this management bean.
+ *
+ * @return the management interface.
+ */
+ public final Class getMBeanInterface()
+ {
+ return iface;
+ }
+
+ /**
+ * Returns the name of the nth parameter of the constructor
+ * that will be used in the supplied {@link MBeanParameterInfo}
+ * instance. This is a customization hook, so that subclasses
+ * can provide a custom name. By default, this calls
+ * <code>param.getName()</code>.
+ *
+ * @param info the {@link MBeanConstructorInfo} instance constructed
+ * via reflection.
+ * @param param the {@link MBeanParameterInfo} instance constructed
+ * via reflection.
+ * @param n the number of the parameter, in order to link it to the
+ * information on the constructor.
+ * @return the name to use in the instance.
+ */
+ protected String getParameterName(MBeanConstructorInfo info,
+ MBeanParameterInfo param, int n)
+ {
+ return param.getName();
+ }
+
+ /**
+ * Returns the name of the nth parameter of the operation
+ * that will be used in the supplied {@link MBeanParameterInfo}
+ * instance. This is a customization hook, so that subclasses
+ * can provide a custom name. By default, this calls
+ * <code>param.getName()</code>.
+ *
+ * @param info the {@link MBeanOperationInfo} instance constructed
+ * via reflection.
+ * @param param the {@link MBeanParameterInfo} instance constructed
+ * via reflection.
+ * @param n the number of the parameter, in order to link it to the
+ * information on the operation.
+ * @return the name to use in the instance.
+ */
+ protected String getParameterName(MBeanOperationInfo info,
+ MBeanParameterInfo param, int n)
+ {
+ return param.getName();
+ }
+
+ /**
+ * Invokes the specified action on the management bean using
+ * the supplied parameters. The signature of the action is
+ * specified by a {@link String} array, which lists the classes
+ * corresponding to each parameter. The class loader used to
+ * load these classes is the same as that used for loading the
+ * management bean itself.
+ *
+ * @param name the name of the action to invoke.
+ * @param params the parameters used to call the action.
+ * @param signature the signature of the action.
+ * @return the return value of the action.
+ * @throws MBeanException if the action throws an exception. The
+ * thrown exception is the cause of this
+ * exception.
+ * @throws ReflectionException if an exception occurred in trying
+ * to use the reflection interface
+ * to invoke the action. The
+ * thrown exception is the cause of
+ * this exception.
+ */
+ public Object invoke(String name, Object[] params, String[] signature)
+ throws MBeanException, ReflectionException
+ {
+ Class[] sigTypes = new Class[signature.length];
+ ClassLoader loader = getClass().getClassLoader();
+ for (int a = 0; a < signature.length; ++a)
+ try
+ {
+ sigTypes[a] = Class.forName(signature[a], true, loader);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new ReflectionException(e, "The class, " + signature[a] +
+ ", in the method signature " +
+ "could not be loaded.");
+ }
+ Method method;
+ try
+ {
+ method = iface.getMethod(name, sigTypes);
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new ReflectionException(e, "The method, " + name +
+ ", could not be found.");
+ }
+ Object result;
+ try
+ {
+ result = method.invoke(impl, params);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new ReflectionException(e, "Failed to call " + name);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ReflectionException(e, "Failed to call " + name);
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new MBeanException((Exception) e.getCause(), "The method "
+ + name + " threw an exception");
+ }
+ return result;
+ }
+
+ /**
+ * Sets the value of the specified attribute of the
+ * management bean. The management bean should perform
+ * a lookup for the named attribute, and sets its value
+ * using the associated setter method, if possible.
+ *
+ * @param attribute the attribute to set.
+ * @throws AttributeNotFoundException if the attribute does not
+ * correspond to an attribute
+ * of the bean.
+ * @throws InvalidAttributeValueException if the value is invalid
+ * for this particular
+ * attribute of the bean.
+ * @throws MBeanException if setting the attribute causes
+ * the bean to throw an exception (which
+ * becomes the cause of this exception).
+ * @throws ReflectionException if an exception occurred in trying
+ * to use the reflection interface
+ * to lookup the attribute. The
+ * thrown exception is the cause of
+ * this exception.
+ * @see #getAttribute(String)
+ */
+ public void setAttribute(Attribute attribute)
+ throws AttributeNotFoundException, InvalidAttributeValueException,
+ MBeanException, ReflectionException
+ {
+ Method setter;
+ String name = attribute.getName();
+ try
+ {
+ setter = iface.getMethod("set" +
+ name.substring(0, 1).toUpperCase() +
+ name.substring(1), null);
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw ((AttributeNotFoundException)
+ new AttributeNotFoundException("The attribute, " + name +
+ ", was not found.").initCause(e));
+ }
+ try
+ {
+ setter.invoke(impl, new Object[] { attribute.getValue() });
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new ReflectionException(e, "Failed to set " + name);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw ((InvalidAttributeValueException)
+ new InvalidAttributeValueException(attribute.getValue() +
+ " is an invalid value for " +
+ name).initCause(e));
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new MBeanException((Exception) e.getCause(), "The getter of "
+ + name + " threw an exception");
+ }
+ }
+
+ /**
+ * Sets the value of each of the specified attributes
+ * to that supplied by the {@link Attribute} object.
+ * The returned list contains the attributes that were
+ * set and their new values.
+ *
+ * @param attributes the attributes to set.
+ * @return a list of the changed attributes.
+ * @see #getAttributes(AttributeList)
+ */
+ public AttributeList setAttributes(AttributeList attributes)
+ {
+ AttributeList list = new AttributeList(attributes.size());
+ Iterator it = attributes.iterator();
+ while (it.hasNext())
+ {
+ try
+ {
+ Attribute attrib = (Attribute) it.next();
+ setAttribute(attrib);
+ list.add(attrib);
+ }
+ catch (AttributeNotFoundException e)
+ {
+ /* Ignored */
+ }
+ catch (InvalidAttributeValueException e)
+ {
+ /* Ignored */
+ }
+ catch (ReflectionException e)
+ {
+ /* Ignored */
+ }
+ catch (MBeanException e)
+ {
+ /* Ignored */
+ }
+ }
+ return list;
+ }
+
+ /**
+ * Replaces the implementation of the interface used by this
+ * instance with the one specified. The new implementation
+ * must be non-null and implement the interface specified on
+ * construction of this instance.
+ *
+ * @throws IllegalArgumentException if <code>impl</code> is <code>null</code>.
+ * @throws NotCompliantMBeanException if <code>impl</code> doesn't implement
+ * the interface or a method appears
+ * in the interface that doesn't comply
+ * with the naming conventions.
+ */
+ public void setImplementation(Object impl)
+ throws NotCompliantMBeanException
+ {
+ if (impl == null)
+ throw new IllegalArgumentException("The specified implementation is null.");
+ if (!(iface.isInstance(impl)))
+ throw new NotCompliantMBeanException("The instance, " + impl +
+ ", is not an instance of " + iface);
+ this.impl = impl;
+ }
+
+}
diff --git a/javax/management/openmbean/ArrayType.java b/javax/management/openmbean/ArrayType.java
new file mode 100644
index 000000000..d2fc398d6
--- /dev/null
+++ b/javax/management/openmbean/ArrayType.java
@@ -0,0 +1,313 @@
+/* ArrayType.java -- Open type descriptor for an array.
+ 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 javax.management.openmbean;
+
+import java.lang.reflect.Array;
+
+import java.util.Arrays;
+
+/**
+ * The open type descriptor for arrays of open data values.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class ArrayType
+ extends OpenType
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 720504429830309770L;
+
+ /**
+ * The number of dimensions arrays of this type has.
+ */
+ private int dimension;
+
+ /**
+ * The element type of arrays of this type.
+ */
+ private OpenType elementType;
+
+ /**
+ * The hash code of this instance.
+ */
+ private transient Integer hashCode;
+
+ /**
+ * The <code>toString()</code> result of this instance.
+ */
+ private transient String string;
+
+ /**
+ * Returns the class name of the array, given the element
+ * class name and its dimensions.
+ *
+ * @param className the name of the class used by the
+ * array's elements.
+ * @param dim the dimensions of the array.
+ * @return the array's class name.
+ */
+ private static String getArrayClassName(String className, int dim)
+ {
+ char[] brackets = new char[dim];
+ Arrays.fill(brackets, '[');
+ return String.valueOf(brackets) + "L" + className;
+ }
+
+ /**
+ * <p>
+ * Constructs a new {@link ArrayType} instance for an array of the
+ * specified type with the supplied number of dimensions. The attributes
+ * used by the superclass, {@link OpenType}, are automatically defined,
+ * based on these values. Both the class name and type name are set
+ * to the value returned by the {@link java.lang.Class#getName()} of
+ * the array's class (i.e. the element type, preceded by n instances of
+ * '[' and an 'L', where n is the number of dimensions the array has).
+ * The description is based upon the template <code>n-dimension array
+ * of e</code>, where n is the number of dimensions of the array, and
+ * e is the element type. The class name of the actual elements is
+ * obtainable by calling {@link OpenType#getClassName()} on the result
+ * of {@link #getElementOpenType()}.
+ * </p>
+ * <p>
+ * As an example, the array type returned by
+ * <code>new ArrayType(6, SimpleType.INTEGER)</code> has the following
+ * values:
+ * </p>
+ * <table>
+ * <th><td>Attribute</td><td>Value</td></th>
+ * <tr><td>Class Name</td><td><code>[[[[[[Ljava.lang.Integer;</code>
+ * </td></tr>
+ * <tr><td>Type Name</td><td><code>[[[[[[Ljava.lang.Integer;</code>
+ * </td></tr>
+ * <tr><td>Description</td><td><code>6-dimension array of
+ * java.lang.Integer</code></td></tr>
+ * <tr><td>Element Type Class Name</td><td><code>java.lang.Integer</code>
+ * </td></tr>
+ * </table>
+ * <p>
+ * The dimensions of the array must be equal to or greater than 1. The
+ * element type must be an instance of {@link SimpleType},
+ * {@link CompositeType} or {@link TabularType}.
+ * </p>
+ *
+ * @param dim the dimensions of the array.
+ * @param elementType the type of the elements of the array.
+ * @throws IllegalArgumentException if <code>dim</code> is less than 1.
+ * @throws OpenDataException if the element type is not an instance of either
+ * {@link SimpleType}, {@link CompositeType}
+ * or {@link TabularType}.
+ */
+ public ArrayType(int dim, OpenType elementType)
+ throws OpenDataException
+ {
+ super(getArrayClassName(elementType.getClassName(), dim),
+ getArrayClassName(elementType.getClassName(), dim),
+ dim + "-dimension array of " + elementType.getClassName());
+ if (dim < 1)
+ throw new IllegalArgumentException("Dimensions must be greater " +
+ "than or equal to 1.");
+ if (!(elementType instanceof SimpleType ||
+ elementType instanceof CompositeType ||
+ elementType instanceof TabularType))
+ throw new OpenDataException("The element type must be a simple " +
+ "type, a composite type or a tabular " +
+ "type.");
+ dimension = dim;
+ this.elementType = elementType;
+ }
+
+ /**
+ * <p>
+ * Compares this array type with another object
+ * for equality. The objects are judged to be equal if:
+ * </p>
+ * <ul>
+ * <li><code>obj</code> is not null.</li>
+ * <li><code>obj</code> is an instance of
+ * {@link ArrayType}.</li>
+ * <li>The dimensions are equal.</li>
+ * <li>The element types are equal.</li>
+ * </ul>
+ *
+ * @param obj the object to compare with.
+ * @return true if the conditions above hold.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ArrayType))
+ return false;
+ ArrayType atype = (ArrayType) obj;
+ return (atype.getDimension() == dimension &&
+ atype.getElementOpenType().equals(elementType));
+ }
+
+ /**
+ * Returns the number of dimensions used by arrays
+ * of this type.
+ *
+ * @return the number of dimensions.
+ */
+ public int getDimension()
+ {
+ return dimension;
+ }
+
+ /**
+ * Returns the open type descriptor which describes
+ * the type of the elements of this array type.
+ *
+ * @return the type of the elements.
+ */
+ public OpenType getElementOpenType()
+ {
+ return elementType;
+ }
+
+ /**
+ * <p>
+ * Returns the hash code of the array type.
+ * This is computed as the sum of the hash code of the
+ * element type together with the number of dimensions
+ * the array has. These are the same elements
+ * of the type that are compared as part of the
+ * {@link #equals(java.lang.Object)} method, thus ensuring
+ * that the hashcode is compatible with the equality
+ * test.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the hash code
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return the hash code of this instance.
+ */
+ public int hashCode()
+ {
+ if (hashCode == null)
+ hashCode = Integer.valueOf(dimension + elementType.hashCode());
+ return hashCode.intValue();
+ }
+
+ /**
+ * <p>
+ * Returns true if the specified object is a member of this
+ * array type. The object is judged to be so if it is
+ * non-null, an array and one of the following two conditions
+ * holds:
+ * </p>
+ * <ul>
+ * <li>This {@link ArrayType} instance has a {@link SimpleType}
+ * as its element type. Thus, the object must have the same
+ * class name as that returned by {@link SimpleType#getClassName()}
+ * for this class.</li>
+ * <li>This {@link ArrayType} instance has a {@link CompositeType}
+ * or a {@link TabularType} as its element type. Thus, the object
+ * must be assignable to such an array, and have elements which
+ * are either null or valid values for the element type.</li>
+ * </ul>
+ *
+ * @param obj the object to test for membership.
+ * @return true if the object is a member of this type.
+ */
+ public boolean isValue(Object obj)
+ {
+ if (obj == null)
+ return false;
+ Class objClass = obj.getClass();
+ if (!(objClass.isArray()))
+ return false;
+ if (elementType instanceof SimpleType)
+ return getClassName().equals(objClass.getName());
+ Class elementClass = null;
+ try
+ {
+ elementClass = Class.forName(getClassName());
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new IllegalStateException("The array type's element " +
+ "class could not be found.", e);
+ }
+ if (!(elementClass.isAssignableFrom(objClass)))
+ return false;
+ for (int a = 0; a < Array.getLength(obj); ++a)
+ {
+ Object elem = Array.get(obj, a);
+ if (elem != null &&
+ (!(elementType.isValue(elem))))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.openmbean.ArrayType</code>)
+ * and each element of the instance which is relevant to
+ * the definition of {@link equals(java.lang.Object)} and
+ * {@link hashCode()} (i.e. the type name, the number of
+ * dimensions and the element type).
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ string = getClass().getName()
+ + "[name=" + getTypeName()
+ + ", dimension=" + dimension
+ + ", elementType=" + elementType
+ + "]";
+ return string;
+ }
+
+}
diff --git a/javax/management/openmbean/CompositeData.java b/javax/management/openmbean/CompositeData.java
new file mode 100644
index 000000000..08f0dc253
--- /dev/null
+++ b/javax/management/openmbean/CompositeData.java
@@ -0,0 +1,154 @@
+/* CompositeData.java -- A composite data structure.
+ 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 javax.management.openmbean;
+
+import java.util.Collection;
+
+/**
+ * Provides an interface to a composite data structure,
+ * in order to aid interoperability. The composite data
+ * structure is represented by mapping field names to
+ * values.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface CompositeData
+{
+
+ /**
+ * Returns true if this {@link CompositeData} instance contains
+ * the specified key. This method always returns false for
+ * an input key equal to <code>null</code> or the empty string.
+ *
+ * @param key the key to find in the structure.
+ * @return true if the key exists.
+ */
+ boolean containsKey(String key);
+
+ /**
+ * Returns true if this {@link CompositeData} instance has
+ * a value equal to that supplied.
+ *
+ * @param value the value to look for.
+ * @return true if the value exists.
+ */
+ boolean containsValue(Object value);
+
+ /**
+ * Compares the specified object with this object for equality.
+ * The object is judged equivalent if it is non-null, and also
+ * an instance of {@link CompositeData} with the same name-value
+ * mappings and types. The two compared instances may be
+ * equivalent even if they represent different implementations of
+ * {@link CompositeData}.
+ *
+ * @param obj the object to compare for equality.
+ * @return true if <code>obj</code> is equal to <code>this</code>.
+ */
+ boolean equals(Object obj);
+
+ /**
+ * Retrieves the value for the specified key.
+ *
+ * @param key the key whose value should be returned.
+ * @return the matching value.
+ * @throws IllegalArgumentException if the key is <code>null</code>
+ * or the empty string.
+ * @throws InvalidKeyException if the key does not exist.
+ */
+ Object get(String key);
+
+ /**
+ * Returns the appropriate value for each key in the given array,
+ * using the same ordering.
+ *
+ * @param keys the keys whose values should be returned.
+ * @return the matching values.
+ * @throws IllegalArgumentException if one of the keys is
+ * <code>null</code> or the
+ * empty string.
+ * @throws InvalidKeyException if one of the keys does not exist.
+ */
+ Object[] getAll(String[] keys);
+
+ /**
+ * Returns the composite type which corresponds to this instance
+ * of {@link CompositeData}.
+ *
+ * @return the composite type for this instance.
+ */
+ CompositeType getCompositeType();
+
+ /**
+ * Returns the hash code of this instance. The hash code is
+ * computed as the sum of the hash codes of all the values plus
+ * the hash code of the composite type. As equality comparisons
+ * take place using this same information, this ensures that
+ * the property, <code>e1.equals(e2)</code> implies
+ * <code>e1.hashCode() == e2.hashCode(), holds for any pair
+ * of instances, <code>e1</code> and <code>e2</code>.
+ *
+ * @return the hash code of this {@link CompositeData}.
+ * @see Object#equals(Object)
+ */
+ int hashCode();
+
+ /**
+ * Returns a textual representation of this instance. The
+ * exact format is left up to the implementation, but it
+ * should contain the name of the implementing class,
+ * the name of the type and a mapping of the form
+ * <code>key=value</code> for each pair of key and value.
+ *
+ * @return a {@link java.lang.String} representation of the
+ * object.
+ */
+ String toString();
+
+ /**
+ * Returns a read-only collection of the values associated with
+ * this instance. The values are sorted using the lexicographic
+ * ordering of the corresponding keys.
+ *
+ * @return the values of this instance.
+ */
+ Collection values();
+
+}
+
diff --git a/javax/management/openmbean/CompositeDataSupport.java b/javax/management/openmbean/CompositeDataSupport.java
new file mode 100644
index 000000000..5d5adb727
--- /dev/null
+++ b/javax/management/openmbean/CompositeDataSupport.java
@@ -0,0 +1,349 @@
+/* CompositeData.java -- A composite data structure implementation.
+ 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 javax.management.openmbean;
+
+import java.io.Serializable;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * Provides an implementation of the {@link CompositeData}
+ * interface.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class CompositeDataSupport
+ implements CompositeData, Serializable
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 8003518976613702244L;
+
+ /**
+ * Mapping of field names to values.
+ *
+ * @serial the map of field names to values.
+ */
+ private SortedMap contents;
+
+ /**
+ * The composite type which represents this composite data instance.
+ *
+ * @serial the type information for this instance.
+ */
+ private CompositeType compositeType;
+
+ /**
+ * Constructs a new {@link CompositeDataSupport} instance with the
+ * specified type using field names and values from the supplied map.
+ * The keys of the map become the field names, while the values
+ * become the values of each respective field. This constructor simply
+ * calls the other constructor, with the two arrays formed using the
+ * keys and values of this map, respectively. Thus, the input parameters
+ * given should conform to the same requirements given there (i.e. no
+ * null values or empty strings).
+ *
+ * @param type the composite type of this composite data structure.
+ * @param items a mapping of field names to values. This should match
+ * the mappings given by the type (i.e. for each mapping
+ * in the type, there should be a corresponding field name
+ * with a value of the correct type).
+ * @throws IllegalArgumentException if the type, the map or any of the keys
+ * or values in the map are <code>null</code>,
+ * or if any key from the map is an empty
+ * string.
+ * @throws OpenDataException if a mismatch occurs between the map and the
+ * field name/type specification given by the
+ * {@link CompositeType} instance. This may be
+ * due to the two having a different size, a
+ * mismatch between keys or an incorrectly typed
+ * value.
+ * @throws ArrayStoreException if one of the keys is not a
+ * {@link java.lang.String} (thus calling a failure
+ * in converting the keys to an array of strings).
+ */
+ public CompositeDataSupport(CompositeType type, Map items)
+ throws OpenDataException
+ {
+ this(type,
+ (String[]) items.keySet().toArray(new String[items.size()]),
+ items.values().toArray());
+ }
+
+ /**
+ * Constructs a new {@link CompositeDataSupport} instance with the
+ * specified type using the supplied arrays of field names and
+ * values. Neither the type, the two arrays or any elements of the
+ * arrays may be <code>null</code>. The {@link java.lang.String}s
+ * within the <code>names</code> array must be non-empty. The
+ * arrays must match in size and order, as each element of the
+ * <code>names</code> array is matched against the corresponding
+ * value in the <code>values</code> array. Internally, the two are
+ * stored in a map, lexographically ordered using the field names.
+ * The data given should also conform to the description of the
+ * instance given by the {@link CompositeType} instance supplied.
+ *
+ * @param type the composite type of this composite data structure.
+ * @param names the field names.
+ * @param values the corresponding values of the fields.
+ * @throws IllegalArgumentException if the type, the arrays or any of the keys
+ * or values in the arrays are <code>null</code>,
+ * or if any key from <code>names</code> is
+ * an empty string. This also occurs if the
+ * arrays differ in length.
+ * @throws OpenDataException if a mismatch occurs between the arrays and the
+ * field name/type specification given by the
+ * {@link CompositeType} instance. This may be
+ * due to a differing number of field names, a
+ * mismatch between names or an incorrectly typed
+ * value.
+ */
+ public CompositeDataSupport(CompositeType type, String[] names, Object[] values)
+ throws OpenDataException
+ {
+ if (type == null)
+ throw new IllegalArgumentException("The given composite type is null.");
+ compositeType = type;
+ if (names == null)
+ throw new IllegalArgumentException("The names array is null.");
+ if (values == null)
+ throw new IllegalArgumentException("The values array is null.");
+ if (names.length != values.length)
+ throw new IllegalArgumentException("The sizes of the arrays differ.");
+ Set typeKeys = type.keySet();
+ if (typeKeys.size() != names.length)
+ throw new OpenDataException("The number of field names does not match " +
+ "the type description.");
+ contents = new TreeMap();
+ for (int a = 0; a < names.length; ++a)
+ {
+ if (names[a] == null)
+ throw new IllegalArgumentException("Element " + a + " of the names " +
+ "array is null.");
+ if (names[a].length() == 0)
+ throw new IllegalArgumentException("Element " + a + " of the names " +
+ "array is an empty string.");
+ if (values[a] == null)
+ throw new IllegalArgumentException("Element " + a + " of the values " +
+ "array is null.");
+ if (!(typeKeys.contains(names[a])))
+ throw new OpenDataException("The name, " + names[a] + ", is not a " +
+ "field in the given type description.");
+ if (!(type.getType(names[a]).isValue(values[a])))
+ throw new OpenDataException("The value, " + values[a] + ", is not a " +
+ "valid value for the " + names[a] + " field.");
+ contents.put(names[a], values[a]);
+ }
+ }
+
+ /**
+ * Returns true if this {@link CompositeData} instance contains
+ * the specified key. This method always returns false for
+ * an input key equal to <code>null</code> or the empty string.
+ *
+ * @param key the key to find in the structure.
+ * @return true if the key exists.
+ */
+ public boolean containsKey(String key)
+ {
+ if (key == null || key.length() == 0)
+ return false;
+ else
+ return contents.containsKey(key);
+ }
+
+ /**
+ * Returns true if this {@link CompositeData} instance has
+ * a value equal to that supplied.
+ *
+ * @param value the value to look for.
+ * @return true if the value exists.
+ */
+ public boolean containsValue(Object value)
+ {
+ return contents.containsValue(value);
+ }
+
+
+ /**
+ * Compares the specified object with this object for equality.
+ * The object is judged equivalent if it is non-null, and also
+ * an instance of {@link CompositeData} with the same name-value
+ * mappings and types. The two compared instances may be
+ * equivalent even if they represent different implementations of
+ * {@link CompositeData}.
+ *
+ * @param obj the object to compare for equality.
+ * @return true if <code>obj</code> is equal to <code>this</code>.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof CompositeData))
+ return false;
+ CompositeData data = (CompositeData) obj;
+ if (!(data.getCompositeType().equals(compositeType)))
+ return false;
+ Iterator it = contents.keySet().iterator();
+ while (it.hasNext())
+ {
+ String key = (String) it.next();
+ if (!(data.containsKey(key)))
+ return false;
+ if (!(data.get(key).equals(contents.get(key))))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Retrieves the value for the specified key.
+ *
+ * @param key the key whose value should be returned.
+ * @return the matching value.
+ * @throws IllegalArgumentException if the key is <code>null</code>
+ * or the empty string.
+ * @throws InvalidKeyException if the key does not exist.
+ */
+ public Object get(String key)
+ {
+ if (key == null)
+ throw new IllegalArgumentException("The supplied key is null.");
+ if (key.length() == 0)
+ throw new IllegalArgumentException("The supplied key is the empty string.");
+ if (!(contents.containsKey(key)))
+ throw new InvalidKeyException("The supplied key does not exist.");
+ return contents.get(key);
+ }
+
+ /**
+ * Returns the appropriate value for each key in the given array,
+ * using the same ordering.
+ *
+ * @param keys the keys whose values should be returned.
+ * @return the matching values.
+ * @throws IllegalArgumentException if one of the keys is
+ * <code>null</code> or the
+ * empty string.
+ * @throws InvalidKeyException if one of the keys does not exist.
+ */
+ public Object[] getAll(String[] keys)
+ {
+ Object[] values = new Object[keys.length];
+ for (int a = 0; a < keys.length; ++a)
+ values[a] = get(keys[a]);
+ return values;
+ }
+
+
+ /**
+ * Returns the composite type which corresponds to this instance
+ * of {@link CompositeData}.
+ *
+ * @return the composite type for this instance.
+ */
+ public CompositeType getCompositeType()
+ {
+ return compositeType;
+ }
+
+ /**
+ * Returns the hash code of this instance. The hash code is
+ * computed as the sum of the hash codes of all the values plus
+ * the hash code of the composite type. As equality comparisons
+ * take place using this same information, this should ensure that
+ * the property, <code>e1.equals(e2)</code> implies
+ * <code>e1.hashCode() == e2.hashCode(), holds for any pair
+ * of instances, <code>e1</code> and <code>e2</code>. However,
+ * this relies on the other instance implementing the
+ * <code>hashCode</code> method correctly, if it is not an
+ * instance of {@link CompositeDataSupport}.
+ *
+ * @return the hash code of this {@link CompositeData}.
+ * @see Object#equals(Object)
+ */
+ public int hashCode()
+ {
+ int code = compositeType.hashCode();
+ Iterator it = values().iterator();
+ while (it.hasNext())
+ code += it.next().hashCode();
+ return code;
+ }
+
+
+ /**
+ * Returns a textual representation of this instance. The
+ * exact format is left up to the implementation, but it
+ * should contain the name of the implementing class,
+ * the name of the type and a mapping of the form
+ * <code>key=value</code> for each pair of key and value.
+ *
+ * @return a {@link java.lang.String} representation of the
+ * object.
+ */
+ public String toString()
+ {
+ return getClass().getName() +
+ "[compositeType=" + compositeType +
+ ",contents=" + contents +
+ "]";
+ }
+
+ /**
+ * Returns a read-only collection of the values associated with
+ * this instance. The values are sorted using the lexicographic
+ * ordering of the corresponding keys.
+ *
+ * @return the values of this instance.
+ */
+ public Collection values()
+ {
+ return Collections.unmodifiableCollection(contents.values());
+ }
+
+}
+
diff --git a/javax/management/openmbean/CompositeType.java b/javax/management/openmbean/CompositeType.java
new file mode 100644
index 000000000..0ae5a4e4b
--- /dev/null
+++ b/javax/management/openmbean/CompositeType.java
@@ -0,0 +1,324 @@
+/* CompositeType.java -- Type descriptor for CompositeData instances.
+ 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 javax.management.openmbean;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * The open type descriptor for instances of the
+ * {@link CompositeData} class.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class CompositeType
+ extends OpenType
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -5366242454346948798L;
+
+ /**
+ * A map of item names to their descriptions.
+ */
+ private TreeMap nameToDescription;
+
+ /**
+ * A map of item names to their types.
+ */
+ private TreeMap nameToType;
+
+ /**
+ * The hash code of this instance.
+ */
+ private transient Integer hashCode;
+
+ /**
+ * The <code>toString()</code> result of this instance.
+ */
+ private transient String string;
+
+ /**
+ * <p>
+ * Constructs a new {@link CompositeType} instance for the given
+ * type name with the specified field names, descriptions and types.
+ * All parameters, and the elements of the array parameters, must be
+ * non-null and {@link java.lang.String} values must be something other
+ * than the empty string. The arrays must be non-empty, and be of
+ * equal size.
+ * </p>
+ * <p>
+ * The result of <code>CompositeData.class.getName()</code> is adopted
+ * as the class name (see {@link OpenType}) and changes to the array
+ * elements following construction of the {@link CompositeType} instance
+ * will <strong>not</strong> affect the values used by the instance.
+ * The field names are sorted in to ascending alphanumeric order internally,
+ * and so ordering can not be used to differentiate between two instances.
+ * </p>
+ *
+ * @param name the name of this composite type.
+ * @param desc a description of this composite type.
+ * @param names the names of each field within the composite type.
+ * @param descs the descriptions of each field within the composite type.
+ * @param types the types of each field within the composite type.
+ * @throws IllegalArgumentException if any validity constraint listed above
+ * is broken.
+ * @throws OpenDataException if duplicate item names are provided. Item names
+ * are case-sensitive, but whitespace is removed
+ * before comparison.
+ */
+ public CompositeType(String name, String desc, String[] names,
+ String[] descs, OpenType[] types)
+ throws OpenDataException
+ {
+ super(CompositeData.class.getName(), name, desc);
+ if (names.length == 0
+ || names.length != descs.length
+ || names.length != types.length)
+ throw new IllegalArgumentException("Arrays must be non-empty " +
+ "and of equal size.");
+ nameToDescription = new TreeMap();
+ for (int a = 0; a < names.length; ++a)
+ {
+ if (names[a] == null)
+ throw new IllegalArgumentException("Name " + a + " is null.");
+ if (descs[a] == null)
+ throw new IllegalArgumentException("Description " + a +
+ " is null.");
+ String fieldName = names[a].trim();
+ if (fieldName.length() == 0)
+ throw new IllegalArgumentException("Name " + a + " is " +
+ "the empty string.");
+ if (descs[a].length() == 0)
+ throw new IllegalArgumentException("Description " + a + " is " +
+ "the empty string.");
+ if (nameToDescription.containsKey(fieldName))
+ throw new OpenDataException(fieldName + " appears more " +
+ "than once.");
+ nameToDescription.put(fieldName, descs[a]);
+ }
+ nameToType = new TreeMap();
+ for (int a = 0; a < names.length; ++a)
+ nameToType.put(names[a].trim(), types[a]);
+ }
+
+ /**
+ * Returns true if this composite data type has a field
+ * with the given name.
+ *
+ * @param name the name of the field to check for.
+ * @return true if a field of that name exists.
+ */
+ public boolean containsKey(String name)
+ {
+ return nameToDescription.containsKey(name);
+ }
+
+ /**
+ * <p>
+ * Compares this composite data type with another object
+ * for equality. The objects are judged to be equal if:
+ * </p>
+ * <ul>
+ * <li><code>obj</code> is not null.</li>
+ * <li><code>obj</code> is an instance of
+ * {@link CompositeType}.</li>
+ * <li>The type names are equal.</li>
+ * <li>The fields and their types match.</li>
+ * </ul>
+ *
+ * @param obj the object to compare with.
+ * @return true if the conditions above hold.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof CompositeType))
+ return false;
+ CompositeType ctype = (CompositeType) obj;
+ if (!(ctype.getTypeName().equals(getTypeName())))
+ return false;
+ Set keys = keySet();
+ if (!(ctype.keySet().equals(keys)))
+ return false;
+ Iterator it = keys.iterator();
+ while (it.hasNext())
+ {
+ String key = (String) it.next();
+ if (!(ctype.getType(key).equals(getType(key))))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns the description for the given field name,
+ * or <code>null</code> if the field name does not
+ * exist within this composite data type.
+ *
+ * @param name the name of the field whose description
+ * should be returned.
+ * @return the description, or <code>null</code> if the
+ * field doesn't exist.
+ */
+ public String getDescription(String name)
+ {
+ return (String) nameToDescription.get(name);
+ }
+
+ /**
+ * Returns the type for the given field name,
+ * or <code>null</code> if the field name does not
+ * exist within this composite data type.
+ *
+ * @param name the name of the field whose type
+ * should be returned.
+ * @return the type, or <code>null</code> if the
+ * field doesn't exist.
+ */
+ public OpenType getType(String name)
+ {
+ return (OpenType) nameToType.get(name);
+ }
+
+ /**
+ * <p>
+ * Returns the hash code of the composite data type.
+ * This is computed as the sum of the hash codes of
+ * each field name and its type, together with the hash
+ * code of the type name. These are the same elements
+ * of the type that are compared as part of the
+ * {@link #equals(java.lang.Object)} method, thus ensuring
+ * that the hashcode is compatible with the equality
+ * test.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the hash code
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return the hash code of this instance.
+ */
+ public int hashCode()
+ {
+ if (hashCode == null)
+ {
+ int elementTotal = 0;
+ Iterator it = nameToType.entrySet().iterator();
+ while (it.hasNext())
+ {
+ Map.Entry entry = (Map.Entry) it.next();
+ elementTotal += (entry.getKey().hashCode() +
+ entry.getValue().hashCode());
+ }
+ hashCode = Integer.valueOf(elementTotal
+ + getTypeName().hashCode());
+ }
+ return hashCode.intValue();
+ }
+
+ /**
+ * Returns true if the specified object is a member of this
+ * composite type. The object is judged to be so if it is
+ * an instance of {@link CompositeData} with an equivalent
+ * type, according to the definition of
+ * {@link #equals(java.lang.Object)} for {@link CompositeType}.
+ *
+ * @param obj the object to test for membership.
+ * @return true if the object is a member of this type.
+ */
+ public boolean isValue(Object obj)
+ {
+ if (obj instanceof CompositeData)
+ {
+ CompositeData data = (CompositeData) obj;
+ return equals(data.getCompositeType());
+ }
+ return false;
+ }
+
+ /**
+ * Returns an unmodifiable {@link java.util.Set}-based
+ * view of the field names that form part of this
+ * {@link CompositeType} instance. The names are stored
+ * in ascending alphanumeric order.
+ *
+ * @return a unmodifiable set containing the field
+ * name {@link java.lang.String}s.
+ */
+ public Set keySet()
+ {
+ return Collections.unmodifiableSet(nameToDescription.keySet());
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.openmbean.CompositeType</code>)
+ * and each element of the instance which is relevant to
+ * the definition of {@link equals(java.lang.Object)} and
+ * {@link hashCode()} (i.e. the type name, and the name
+ * and type of each field).
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ string = getClass().getName()
+ + "[name=" + getTypeName()
+ + ", fields=" + nameToType
+ + "]";
+ return string;
+ }
+
+}
diff --git a/javax/management/openmbean/InvalidKeyException.java b/javax/management/openmbean/InvalidKeyException.java
new file mode 100644
index 000000000..5f0cf7603
--- /dev/null
+++ b/javax/management/openmbean/InvalidKeyException.java
@@ -0,0 +1,77 @@
+/* InvalidKeyException.java -- Thrown by an invalid composite/tabular key.
+ 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 javax.management.openmbean;
+
+/**
+ * Thrown when an invalid key (a field name or row index) is
+ * passed to a method of the {@link CompositeData} or
+ * {@link TabularData} classes.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class InvalidKeyException
+ extends IllegalArgumentException
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 4224269443946322062L;
+
+ /**
+ * Constructs a new <code>InvalidKeyException</code>.
+ */
+ public InvalidKeyException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>InvalidKeyException</code>
+ * with the specified message.
+ *
+ * @param message the error message to give to the user.
+ */
+ public InvalidKeyException(String message)
+ {
+ super(message);
+ }
+
+}
+
diff --git a/javax/management/openmbean/InvalidOpenTypeException.java b/javax/management/openmbean/InvalidOpenTypeException.java
new file mode 100644
index 000000000..9c9ff8cfa
--- /dev/null
+++ b/javax/management/openmbean/InvalidOpenTypeException.java
@@ -0,0 +1,76 @@
+/* InvalidOpenTypeException.java -- Thrown by an invalid open type.
+ 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 javax.management.openmbean;
+
+/**
+ * Thrown when a open data value has an erroneous open
+ * type.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class InvalidOpenTypeException
+ extends IllegalArgumentException
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -2837312755412327534L;
+
+ /**
+ * Constructs a new <code>InvalidOpenTypeException</code>.
+ */
+ public InvalidOpenTypeException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>InvalidOpenTypeException</code>
+ * with the specified message.
+ *
+ * @param message the error message to give to the user.
+ */
+ public InvalidOpenTypeException(String message)
+ {
+ super(message);
+ }
+
+}
+
diff --git a/javax/management/openmbean/KeyAlreadyExistsException.java b/javax/management/openmbean/KeyAlreadyExistsException.java
new file mode 100644
index 000000000..cc6bba636
--- /dev/null
+++ b/javax/management/openmbean/KeyAlreadyExistsException.java
@@ -0,0 +1,77 @@
+/* KeyAlreadyExistsException.java -- Thrown when a key clashes with another.
+ 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 javax.management.openmbean;
+
+/**
+ * Thrown when a key (a field name or row index) is passed to a method
+ * of the {@link CompositeData} or {@link TabularData} classes and it
+ * is found to already be in use.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class KeyAlreadyExistsException
+ extends IllegalArgumentException
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 1845183636745282866L;
+
+ /**
+ * Constructs a new <code>KeyAlreadyExistsException</code>.
+ */
+ public KeyAlreadyExistsException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>KeyAlreadyExistsException</code>
+ * with the specified message.
+ *
+ * @param message the error message to give to the user.
+ */
+ public KeyAlreadyExistsException(String message)
+ {
+ super(message);
+ }
+
+}
+
diff --git a/javax/management/openmbean/OpenDataException.java b/javax/management/openmbean/OpenDataException.java
new file mode 100644
index 000000000..a476cc1d4
--- /dev/null
+++ b/javax/management/openmbean/OpenDataException.java
@@ -0,0 +1,79 @@
+/* OpenDataException.java -- Thrown by invalid open bean data.
+ 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 javax.management.openmbean;
+
+import javax.management.JMException;
+
+/**
+ * Thrown when an instance of one of the open types, open
+ * data objects or open metadata information objects could
+ * not be created due to invalid construction parameters.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class OpenDataException
+ extends JMException
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 8346311255433349870L;
+
+ /**
+ * Constructs a new <code>OpenDataException</code>.
+ */
+ public OpenDataException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>OpenDataException</code>
+ * with the specified message.
+ *
+ * @param message the error message to give to the user.
+ */
+ public OpenDataException(String message)
+ {
+ super(message);
+ }
+
+}
+
diff --git a/javax/management/openmbean/OpenMBeanAttributeInfo.java b/javax/management/openmbean/OpenMBeanAttributeInfo.java
new file mode 100644
index 000000000..1b276fd19
--- /dev/null
+++ b/javax/management/openmbean/OpenMBeanAttributeInfo.java
@@ -0,0 +1,120 @@
+/* OpenMBeanAttributeInfo.java -- Open typed info about an attribute.
+ 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 javax.management.openmbean;
+
+/**
+ * Describes an attribute associated with an open management bean.
+ * This interface includes those methods specified by {@link
+ * javax.management.MBeanAttributeInfo}, so implementations should
+ * extend this class.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface OpenMBeanAttributeInfo
+ extends OpenMBeanParameterInfo
+{
+
+ /**
+ * Compares this attribute with the supplied object. This returns
+ * true iff the object is an instance of {@link OpenMBeanAttributeInfo}
+ * with an equal name and open type, the same default, minimum,
+ * maximum and legal values and the same access properties
+ * ({@link #isIs()}, {@link #isReadable()}, {@link #isWritable()}).
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link OpenMBeanParameterInfo}
+ * instance,
+ * <code>name.equals(object.getName())</code>,
+ * <code>openType.equals(object.getOpenType())</code>,
+ * <code>defaultValue.equals(object.getDefaultValue())</code>,
+ * <code>minValue.equals(object.getMinValue())</code>,
+ * <code>maxValue.equals(object.getMaxValue())</code>,
+ * <code>legalValues.equals(object.getLegalValues())</code>,
+ * <code>is == object.isIs()</code>,
+ * <code>isRead == object.isReadable()</code>,
+ * and <code>isWrite == object.isWritable()</code>.
+ */
+ boolean equals(Object obj);
+
+ /**
+ * Returns the hashcode of the attribute information as the sum of
+ * the hashcodes of the name, open type, default value, maximum
+ * value, minimum value, the set of legal values and the access
+ * properties.
+ *
+ * @return the hashcode of the attribute information.
+ */
+ int hashCode();
+
+ /**
+ * Returns true if the accessor method of this attribute
+ * is of the form <code>isXXX</code>.
+ *
+ * @return true if the accessor takes the form <code>isXXX</code>.
+ */
+ boolean isIs();
+
+ /**
+ * Returns true if value of this attribute can be read.
+ *
+ * @return true if the value of the attribute can be read.
+ */
+ boolean isReadable();
+
+ /**
+ * Returns true if the value of this attribute can be changed.
+ *
+ * @return true if the value of the attribute can be changed.
+ */
+ boolean isWritable();
+
+ /**
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.openmbean.OpenMBeanAttributeInfo</code>)
+ * along with the name, open type, default, minimum, maximum
+ * and legal values of the parameter and the access permissions
+ * ({@link #isIs()}, {@link #isReadable()}, {@link #isWritable()}).
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ String toString();
+
+}
diff --git a/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java b/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java
new file mode 100644
index 000000000..83e043640
--- /dev/null
+++ b/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java
@@ -0,0 +1,546 @@
+/* OpenMBeanAttributeInfoSupport.java -- Open typed info about an attribute.
+ 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 javax.management.openmbean;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.management.MBeanAttributeInfo;
+
+/**
+ * Describes an attribute of an open management bean.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class OpenMBeanAttributeInfoSupport
+ extends MBeanAttributeInfo
+ implements OpenMBeanAttributeInfo
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -4867215622149721849L;
+
+ /**
+ * The open type of the attribute.
+ */
+ private OpenType openType;
+
+ /**
+ * The default value of the attribute (may be <code>null</code>).
+ */
+ private Object defaultValue;
+
+ /**
+ * The possible legal values of the attribute (may be <code>null</code>).
+ */
+ private Set legalValues;
+
+ /**
+ * The minimum value of the attribute (may be <code>null</code>).
+ */
+ private Comparable minValue;
+
+ /**
+ * The maximum value of the attribute (may be <code>null</code>).
+ */
+ private Comparable maxValue;
+
+ /**
+ * The hash code of this instance.
+ */
+ private transient Integer hashCode;
+
+ /**
+ * The <code>toString()</code> result of this instance.
+ */
+ private transient String string;
+
+ /**
+ * Constructs a new {@link OpenMBeanAttributeInfo} using the
+ * specified name, description, open type and access properties.
+ * The name, description and open type may not be <code>null</code>
+ * and the name and description may not be equal to the empty
+ * string.
+ *
+ * @param name the name of the attribute.
+ * @param desc a description of the attribute.
+ * @param type the open type of the attribute.
+ * @param isReadable true if the attribute's value can be read.
+ * @param isWritable true if the attribute's value can be changed.
+ * @param isIs true if the attribute uses an accessor of the form isXXX.
+ * @throws IllegalArgumentException if the name, description or
+ * open type are <code>null</code>
+ * or the name or description are
+ * the empty string.
+ */
+ public OpenMBeanAttributeInfoSupport(String name, String desc, OpenType type,
+ boolean isReadable, boolean isWritable,
+ boolean isIs)
+ {
+ super(name, type == null ? null : type.getClassName(), desc, isReadable,
+ isWritable, isIs);
+ if (name == null)
+ throw new IllegalArgumentException("The name may not be null.");
+ if (desc == null)
+ throw new IllegalArgumentException("The description may not be null.");
+ if (type == null)
+ throw new IllegalArgumentException("The type may not be null.");
+ if (name.length() == 0)
+ throw new IllegalArgumentException("The name may not be the empty string.");
+ if (desc.length() == 0)
+ throw new IllegalArgumentException("The description may not be the " +
+ "empty string.");
+ }
+
+ /**
+ * Constructs a new {@link OpenMBeanAttributeInfo} using the
+ * specified name, description, open type and default value. The
+ * name, description and open type cannot be <code>null</code> and
+ * the name and description may not be equal to the empty string.
+ * The default value may be <code>null</code>. If non-null, it must
+ * be a valid value of the given open type. Default values are not
+ * applicable to the open types, {@link ArrayType} and {@link
+ * TabularType}.
+ *
+ * @param name the name of the attribute.
+ * @param desc a description of the attribute.
+ * @param type the open type of the attribute.
+ * @param isReadable true if the attribute's value can be read.
+ * @param isWritable true if the attribute's value can be changed.
+ * @param isIs true if the attribute uses an accessor of the form isXXX.
+ * @param defaultValue the default value of the attribute.
+ * @throws IllegalArgumentException if the name, description or
+ * open type are <code>null</code>
+ * or the name or description are
+ * the empty string.
+ * @throws OpenDataException if <code>defaultValue<code> is non-null
+ * and is either not a value of the given
+ * open type or the open type is an instance
+ * of {@link ArrayType} or {@link TabularType}.
+ */
+ public OpenMBeanAttributeInfoSupport(String name, String desc, OpenType type,
+ boolean isReadable, boolean isWritable,
+ boolean isIs, Object defaultValue)
+ throws OpenDataException
+ {
+ this(name, desc, type, isReadable, isWritable, isIs, defaultValue, null);
+ }
+
+ /**
+ * <p>
+ * Constructs a new {@link OpenMBeanAttributeInfo} using the
+ * specified name, description, open type, access properties,
+ * default, maximum and minimum values. The name, description
+ * and open type cannot be <code>null</code> and the name and
+ * description may not be equal to the empty string. The
+ * default, maximum and minimum values may be <code>null</code>.
+ * The following conditions apply when the attributes mentioned
+ * are non-null:
+ * </p>
+ * <ul>
+ * <li>The values must be valid values for the given open type.</li>
+ * <li>Default values are not applicable to the open types, {@link
+ * ArrayType} and {@link TabularType}.</li>
+ * <li>The minimum value must be smaller than or equal to the maximum value
+ * (literally, <code>minValue.compareTo(maxValue) <= 0</code>.</li>
+ * <li>The minimum value must be smaller than or equal to the default value
+ * (literally, <code>minValue.compareTo(defaultValue) <= 0</code>.</li>
+ * <li>The default value must be smaller than or equal to the maximum value
+ * (literally, <code>defaultValue.compareTo(maxValue) <= 0</code>.</li>
+ * </ul>
+ *
+ * @param name the name of the attribute.
+ * @param desc a description of the attribute.
+ * @param type the open type of the attribute.
+ * @param isReadable true if the attribute's value can be read.
+ * @param isWritable true if the attribute's value can be changed.
+ * @param isIs true if the attribute uses an accessor of the form isXXX.
+ * @param defaultValue the default value of the attribute, or <code>null</code>.
+ * @param minimumValue the minimum value of the attribute, or <code>null</code>.
+ * @param maximumValue the maximum value of the attribute, or <code>null</code>.
+ * @throws IllegalArgumentException if the name, description or
+ * open type are <code>null</code>
+ * or the name or description are
+ * the empty string.
+ * @throws OpenDataException if any condition in the list above is broken.
+ */
+ public OpenMBeanAttributeInfoSupport(String name, String desc, OpenType type,
+ boolean isReadable, boolean isWritable,
+ boolean isIs, Object defaultValue,
+ Comparable minimumValue,
+ Comparable maximumValue)
+ throws OpenDataException
+ {
+ this(name, desc, type, isReadable, isWritable, isIs);
+ if (defaultValue != null && !(type.isValue(defaultValue)))
+ throw new OpenDataException("The default value is not a member of the " +
+ "open type given.");
+ if (minimumValue != null && !(type.isValue(minimumValue)))
+ throw new OpenDataException("The minimum value is not a member of the " +
+ "open type given.");
+ if (maximumValue != null && !(type.isValue(maximumValue)))
+ throw new OpenDataException("The maximum value is not a member of the " +
+ "open type given.");
+ if (defaultValue != null && (type instanceof ArrayType ||
+ type instanceof TabularType))
+ throw new OpenDataException("Default values are not applicable for " +
+ "array or tabular types.");
+ if (minValue != null && maxValue != null
+ && minValue.compareTo(maxValue) > 0)
+ throw new OpenDataException("The minimum value is greater than the " +
+ "maximum.");
+ if (minValue != null && defaultValue != null
+ && minValue.compareTo(defaultValue) > 0)
+ throw new OpenDataException("The minimum value is greater than the " +
+ "default.");
+ if (defaultValue != null && maxValue != null
+ && maxValue.compareTo(defaultValue) < 0)
+ throw new OpenDataException("The default value is greater than the " +
+ "maximum.");
+
+ openType = type;
+ this.defaultValue = defaultValue;
+ minValue = minimumValue;
+ maxValue = maximumValue;
+ }
+
+ /**
+ * <p>
+ * Constructs a new {@link OpenMBeanAttributeInfo} using the
+ * specified name, description, open type, access properties, default
+ * value and set of legal values. The name, description and open type
+ * cannot be <code>null</code> and the name and description may not be
+ * equal to the empty string. The default, maximum and minimum values
+ * may be <code>null</code>. The following conditions apply when the
+ * attributes mentioned are non-null:
+ * </p>
+ * <ul>
+ * <li>The default value and each of the legal values must be a valid
+ * value for the given open type.</li>
+ * <li>Default and legal values are not applicable to the open types, {@link
+ * ArrayType} and {@link TabularType}.</li>
+ * <li>The default value is not in the set of legal values.</li>
+ * </ul>
+ * <p>
+ * The legal values are copied from the array into a unmodifiable set,
+ * so future modifications to the array have no effect.
+ * </p>
+ *
+ * @param name the name of the attribute.
+ * @param desc a description of the attribute.
+ * @param type the open type of the attribute.
+ * @param isReadable true if the attribute's value can be read.
+ * @param isWritable true if the attribute's value can be changed.
+ * @param isIs true if the attribute uses an accessor of the form isXXX.
+ * @param defaultValue the default value of the attribute, or <code>null</code>.
+ * @param legalValues the legal values of the attribute. May be
+ * <code>null</code> or an empty array.
+ * @throws IllegalArgumentException if the name, description or
+ * open type are <code>null</code>
+ * or the name or description are
+ * the empty string.
+ * @throws OpenDataException if any condition in the list above is broken.
+ */
+ public OpenMBeanAttributeInfoSupport(String name, String desc, OpenType type,
+ boolean isReadable, boolean isWritable,
+ boolean isIs, Object defaultValue,
+ Object[] legalValues)
+ throws OpenDataException
+ {
+ this(name, desc, type, isReadable, isWritable, isIs);
+ if (defaultValue != null && !(type.isValue(defaultValue)))
+ throw new OpenDataException("The default value is not a member of the " +
+ "open type given.");
+ if (defaultValue != null && (type instanceof ArrayType ||
+ type instanceof TabularType))
+ throw new OpenDataException("Default values are not applicable for " +
+ "array or tabular types.");
+ if (legalValues != null && (type instanceof ArrayType ||
+ type instanceof TabularType))
+ throw new OpenDataException("Legal values are not applicable for " +
+ "array or tabular types.");
+ if (legalValues != null && legalValues.length > 0)
+ {
+ Set lv = new HashSet(legalValues.length);
+ for (int a = 0; a < legalValues.length; ++a)
+ {
+ if (legalValues[a] != null &&
+ !(type.isValue(legalValues[a])))
+ throw new OpenDataException("The legal value, "
+ + legalValues[a] +
+ "is not a member of the " +
+ "open type given.");
+ lv.add(legalValues[a]);
+ }
+ if (defaultValue != null && !(lv.contains(defaultValue)))
+ throw new OpenDataException("The default value is not in the set " +
+ "of legal values.");
+ this.legalValues = Collections.unmodifiableSet(lv);
+ }
+ openType = type;
+ this.defaultValue = defaultValue;
+ }
+
+ /**
+ * Compares this attribute with the supplied object. This returns
+ * true iff the object is an instance of {@link OpenMBeanAttributeInfo}
+ * with an equal name and open type and the same default, minimum,
+ * maximum and legal values and the same access properties.
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link OpenMBeanAttributeInfo}
+ * instance,
+ * <code>name.equals(object.getName())</code>,
+ * <code>openType.equals(object.getOpenType())</code>,
+ * <code>isRead == object.isReadable()</code>,
+ * <code>isWrite == object.isWritable()</code>,
+ * <code>isIs == object.isIs()</code>,
+ * <code>defaultValue.equals(object.getDefaultValue())</code>,
+ * <code>minValue.equals(object.getMinValue())</code>,
+ * <code>maxValue.equals(object.getMaxValue())</code>,
+ * and <code>legalValues.equals(object.getLegalValues())</code>.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof OpenMBeanAttributeInfo))
+ return false;
+ OpenMBeanAttributeInfo o = (OpenMBeanAttributeInfo) obj;
+ return getName().equals(o.getName()) &&
+ openType.equals(o.getOpenType()) &&
+ isReadable() == o.isReadable() &&
+ isWritable() == o.isWritable() &&
+ isIs() == o.isIs() &&
+ (defaultValue == null ? o.getDefaultValue() == null :
+ defaultValue.equals(o.getDefaultValue())) &&
+ (minValue == null ? o.getMinValue() == null :
+ minValue.equals(o.getMinValue())) &&
+ (maxValue == null ? o.getMaxValue() == null :
+ maxValue.equals(o.getMaxValue())) &&
+ (legalValues == null ? o.getLegalValues() == null :
+ legalValues.equals(o.getLegalValues()));
+ }
+
+ /**
+ * Returns the default value of this attribute, or <code>null</code>
+ * if there is no default value.
+ *
+ * @return the default value of the attribute, or <code>null</code>
+ * if there is no default.
+ */
+ public Object getDefaultValue()
+ {
+ return defaultValue;
+ }
+
+ /**
+ * Returns a {@link java.util.Set} enumerating the legal values
+ * of this attribute, or <code>null</code> if no such limited
+ * set exists for this attribute.
+ *
+ * @return a set of legal values, or <code>null</code> if no such
+ * set exists.
+ */
+ public Set getLegalValues()
+ {
+ return legalValues;
+ }
+
+ /**
+ * Returns the maximum value of this attribute, or <code>null</code>
+ * if there is no maximum.
+ *
+ * @return the maximum value, or <code>null</code> if none exists.
+ */
+ public Comparable getMaxValue()
+ {
+ return maxValue;
+ }
+
+ /**
+ * Returns the minimum value of this attribute, or <code>null</code>
+ * if there is no minimum.
+ *
+ * @return the minimum value, or <code>null</code> if none exists.
+ */
+ public Comparable getMinValue()
+ {
+ return minValue;
+ }
+
+ /**
+ * Returns the open type instance which represents the type of this
+ * attribute.
+ *
+ * @return the open type of this attribute.
+ */
+ public OpenType getOpenType()
+ {
+ return openType;
+ }
+
+ /**
+ * Returns true if this attribute has a default value
+ * (i.e. the value is non-null).
+ *
+ * @return true if this attribute has a default.
+ */
+ public boolean hasDefaultValue()
+ {
+ return defaultValue != null;
+ }
+
+ /**
+ * <p>
+ * Returns the hashcode of the attribute information as the sum of
+ * the hashcodes of the name, open type, default value, maximum
+ * value, minimum value and the set of legal values.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the hash code
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return the hashcode of the attribute information.
+ */
+ public int hashCode()
+ {
+ if (hashCode == null)
+ hashCode = Integer.valueOf(getName().hashCode() +
+ openType.hashCode() +
+ Boolean.valueOf(isReadable()).hashCode() +
+ (2 *
+ Boolean.valueOf(isWritable()).hashCode()) +
+ (4 * Boolean.valueOf(isIs()).hashCode()) +
+ (defaultValue == null ? 0 :
+ defaultValue.hashCode()) +
+ (minValue == null ? 0 :
+ minValue.hashCode()) +
+ (maxValue == null ? 0 :
+ maxValue.hashCode()) +
+ (legalValues == null ? 0 :
+ legalValues.hashCode()));
+ return hashCode.intValue();
+ }
+
+ /**
+ * Returns true if there is a set of legal values for this
+ * attribute (i.e. the value is non-null).
+ *
+ * @return true if a set of legal values exists for this
+ * attribute.
+ */
+ public boolean hasLegalValues()
+ {
+ return legalValues != null;
+ }
+
+ /**
+ * Returns true if there is a maximum value for this attribute
+ * (i.e. the value is non-null).
+ *
+ * @return true if a maximum value exists for this attribute.
+ */
+ public boolean hasMaxValue()
+ {
+ return maxValue != null;
+ }
+
+ /**
+ * Returns true if there is a minimum value for this attribute.
+ * (i.e. the value is non-null).
+ *
+ * @return true if a minimum value exists for this attribute.
+ */
+ public boolean hasMinValue()
+ {
+ return minValue != null;
+ }
+
+ /**
+ * Returns true if the specified object is a valid value for
+ * this attribute.
+ *
+ * @param obj the object to test.
+ * @return true if <code>obj</code> is a valid value for this
+ * attribute.
+ */
+ public boolean isValue(Object obj)
+ {
+ return openType.isValue(obj);
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.openmbean.OpenMBeanAttributeInfo</code>)
+ * along with the name, open type, access properties, default,
+ * minimum, maximum and legal values of the attribute.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ string = getClass().getName()
+ + "[name=" + getName()
+ + ",openType=" + openType
+ + ",isReadable=" + isReadable()
+ + ",isWritable=" + isWritable()
+ + ",isIs=" + isIs()
+ + ",defaultValue=" + defaultValue
+ + ",minValue=" + minValue
+ + ",maxValue=" + maxValue
+ + ",legalValues=" + legalValues
+ + "]";
+ return string;
+ }
+
+}
diff --git a/javax/management/openmbean/OpenMBeanConstructorInfo.java b/javax/management/openmbean/OpenMBeanConstructorInfo.java
new file mode 100644
index 000000000..34cef131f
--- /dev/null
+++ b/javax/management/openmbean/OpenMBeanConstructorInfo.java
@@ -0,0 +1,112 @@
+/* OpenMBeanConstructorInfo.java -- Open typed info about a constructor.
+ 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 javax.management.openmbean;
+
+import javax.management.MBeanParameterInfo;
+
+/**
+ * Describes a constructor for an open management bean.
+ * This interface includes those methods specified by {@link
+ * javax.management.MBeanConstructorInfo}, so implementations should
+ * extend this class. The {@link #getSignature()} method should
+ * return an array containing instances of {@link OpenMBeanParameterInfo}.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface OpenMBeanConstructorInfo
+{
+
+ /**
+ * Compares this attribute with the supplied object. This returns
+ * true iff the object is an instance of {@link OpenMBeanConstructorInfo}
+ * with an equal name and signature.
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link OpenMBeanParameterInfo}
+ * instance,
+ * <code>name.equals(object.getName())</code>,
+ * and <code>signature.equals(object.getSignature())</code>.
+ */
+ boolean equals(Object obj);
+
+ /**
+ * Returns a description of this constructor.
+ *
+ * @return a human-readable description.
+ */
+ String getDescription();
+
+ /**
+ * Returns the name of this constructor.
+ *
+ * @return the name of the constructor.
+ */
+ String getName();
+
+ /**
+ * Returns the constructor's signature, in the form of
+ * information on each parameter. Each parameter is
+ * described by an instance of {@link OpenMBeanParameterInfo}.
+ *
+ * @return an array of {@link OpenMBeanParameterInfo} objects,
+ * describing the constructor parameters.
+ */
+ MBeanParameterInfo[] getSignature();
+
+ /**
+ * Returns the hashcode of the constructor information as the sum of
+ * the hashcodes of the name and signature (calculated by
+ * <code>java.util.Arrays.asList(signature).hashCode()</code>).
+ *
+ * @return the hashcode of the constructor information.
+ */
+ int hashCode();
+
+ /**
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.openmbean.OpenMBeanConstructorInfo</code>)
+ * along with the name and signature.
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ String toString();
+
+}
diff --git a/javax/management/openmbean/OpenMBeanConstructorInfoSupport.java b/javax/management/openmbean/OpenMBeanConstructorInfoSupport.java
new file mode 100644
index 000000000..9dac01a59
--- /dev/null
+++ b/javax/management/openmbean/OpenMBeanConstructorInfoSupport.java
@@ -0,0 +1,174 @@
+/* OpenMBeanConstructorInfoSupport.java -- Open typed info about an constructor.
+ 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 javax.management.openmbean;
+
+import java.util.Arrays;
+
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanParameterInfo;
+
+/**
+ * Describes a constructor for an open management bean.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class OpenMBeanConstructorInfoSupport
+ extends MBeanConstructorInfo
+ implements OpenMBeanConstructorInfo
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -4400441579007477003L;
+
+ /**
+ * The hash code of this instance.
+ */
+ private transient Integer hashCode;
+
+ /**
+ * The <code>toString()</code> result of this instance.
+ */
+ private transient String string;
+
+ /**
+ * Constructs a @link{OpenMBeanConstructorInfo} with the specified
+ * name, description and parameter information. A <code>null</code>
+ * value for the parameter information is the same as passing in
+ * an empty array. Neither the name nor the description may be
+ * null or equal to the empty string. A copy of the parameter array
+ * is taken, so later changes have no effect.
+ *
+ * @param name the name of the constructor.
+ * @param desc a description of the constructor.
+ * @param sig the signature of the constructor, as a series
+ * of {@link MBeanParameterInfo} objects, one for
+ * each parameter.
+ * @throws IllegalArgumentException if the name or description is
+ * either <code>null</code>
+ * or the empty string.
+ * @throws ArrayStoreException if the members of the signature array
+ * are not assignable to
+ * {@link javax.management.MBeanParameterInfo}
+ */
+ public OpenMBeanConstructorInfoSupport(String name, String desc,
+ OpenMBeanParameterInfo[] sig)
+ {
+ super(name, desc, (MBeanParameterInfo[]) sig);
+ if (name == null)
+ throw new IllegalArgumentException("The name may not be null.");
+ if (desc == null)
+ throw new IllegalArgumentException("The description may not be null.");
+ if (name.length() == 0)
+ throw new IllegalArgumentException("The name may not be the empty string.");
+ if (desc.length() == 0)
+ throw new IllegalArgumentException("The description may not be the " +
+ "empty string.");
+ }
+
+ /**
+ * Compares this attribute with the supplied object. This returns
+ * true iff the object is an instance of {@link OpenMBeanConstructorInfo}
+ * with an equal name and signature.
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link OpenMBeanParameterInfo}
+ * instance,
+ * <code>name.equals(object.getName())</code>,
+ * and <code>signature.equals(object.getSignature())</code>.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof OpenMBeanConstructorInfo))
+ return false;
+ OpenMBeanConstructorInfo o = (OpenMBeanConstructorInfo) obj;
+ return getName().equals(o.getName()) &&
+ getSignature().equals(o.getSignature());
+ }
+
+ /**
+ * <p>
+ * Returns the hashcode of the constructor information as the sum of
+ * the hashcodes of the name and signature (calculated by
+ * <code>java.util.Arrays.asList(signature).hashCode()</code>).
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return the hashcode of the constructor information.
+ */
+ public int hashCode()
+ {
+ if (hashCode == null)
+ hashCode = Integer.valueOf(getName().hashCode() +
+ Arrays.asList(getSignature()).hashCode());
+ return hashCode.intValue();
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.openmbean.OpenMBeanConstructorInfo</code>)
+ * along with the name and signature.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ string = getClass().getName()
+ + "[name=" + getName()
+ + ",signature=" + Arrays.toString(getSignature())
+ + "]";
+ return string;
+ }
+
+}
diff --git a/javax/management/openmbean/OpenMBeanInfo.java b/javax/management/openmbean/OpenMBeanInfo.java
new file mode 100644
index 000000000..5aa4df451
--- /dev/null
+++ b/javax/management/openmbean/OpenMBeanInfo.java
@@ -0,0 +1,154 @@
+/* OpenMBeanInfo.java -- Open typed info about a management bean.
+ 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 javax.management.openmbean;
+
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+
+/**
+ * Describes an open management bean. Open management beans are
+ * management beans where {@link
+ * javax.management.DynamicMBean#getMBeanInfo()} returns an
+ * implementation of this interface. This interface includes those
+ * methods specified by {@link javax.management.MBeanInfo},
+ * so implementations should extend this class. Each method
+ * which returns an array of one of the <code>MBeanXXXInfo</code>
+ * classes should return an array containing instances
+ * of the equivalent open version (<code>OpenMBeanXXXInfo</code>).
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface OpenMBeanInfo
+{
+
+ /**
+ * Compares this attribute with the supplied object. This returns
+ * true iff the object is an instance of {@link OpenMBeanInfo}
+ * with the same class name and equal instances of the info classes.
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link OpenMBeanInfo}
+ * instance,
+ * <code>className.equals(object.getClassName())</code>
+ * and each info class has an equal in the other object.
+ */
+ boolean equals(Object obj);
+
+ /**
+ * Returns descriptions of each of the attributes provided by this
+ * management bean. The elements should be implementations of the
+ * {@link OpenMBeanAttributeInfo} class.
+ *
+ * @return an array of {@link OpenMBeanAttributeInfo} objects,
+ * representing the attributes emitted by this
+ * management bean.
+ */
+ MBeanAttributeInfo[] getAttributes();
+
+ /**
+ * Returns the class name of the management bean.
+ *
+ * @return the bean's class name.
+ */
+ String getClassName();
+
+ /**
+ * Returns descriptions of each of the constructors provided by this
+ * management bean. The elements should be implementations of the
+ * {@link OpenMBeanConstructorInfo} class.
+ *
+ * @return an array of {@link OpenMBeanConstructorInfo} objects,
+ * representing the constructors emitted by this
+ * management bean.
+ */
+ MBeanConstructorInfo[] getConstructors();
+
+ /**
+ * Returns a description of this operation.
+ *
+ * @return a human-readable description.
+ */
+ String getDescription();
+
+ /**
+ * Returns descriptions of each of the notifications provided by this
+ * management bean. The elements should be implementations of the
+ * {@link OpenMBeanNotificationInfo} class.
+ *
+ * @return an array of {@link OpenMBeanNotificationInfo} objects,
+ * representing the notifications emitted by this
+ * management bean.
+ */
+ MBeanNotificationInfo[] getNotifications();
+
+ /**
+ * Returns descriptions of each of the operations provided by this
+ * management bean. The elements should be implementations of the
+ * {@link OpenMBeanOperationInfo} class.
+ *
+ * @return an array of {@link OpenMBeanOperationInfo} objects,
+ * representing the operations emitted by this
+ * management bean.
+ */
+ MBeanOperationInfo[] getOperations();
+
+ /**
+ * Returns the hashcode of the bean information as the sum of the
+ * hashcodes of the class name and each array (calculated using
+ * java.util.HashSet(<code>java.util.Arrays.asList(signature)).hashCode()</code>).
+ *
+ * @return the hashcode of the bean information.
+ */
+ int hashCode();
+
+ /**
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.openmbean.OpenMBeanInfo</code>)
+ * along with the class name and textual representations
+ * of each array.
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ String toString();
+
+}
diff --git a/javax/management/openmbean/OpenMBeanInfoSupport.java b/javax/management/openmbean/OpenMBeanInfoSupport.java
new file mode 100644
index 000000000..5f8d55b83
--- /dev/null
+++ b/javax/management/openmbean/OpenMBeanInfoSupport.java
@@ -0,0 +1,191 @@
+/* OpenMBeanInfoSupport.java -- Open typed info about a bean.
+ 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 javax.management.openmbean;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+import javax.management.MBeanInfo;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+
+/**
+ * Describes an open management bean.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class OpenMBeanInfoSupport
+ extends MBeanInfo
+ implements OpenMBeanInfo
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 4349395935420511492L;
+
+ /**
+ * The hash code of this instance.
+ */
+ private transient Integer hashCode;
+
+ /**
+ * The <code>toString()</code> result of this instance.
+ */
+ private transient String string;
+
+ /**
+ * Constructs a new {@link OpenMBeanInfo} using the supplied
+ * class name and description with the given attributes,
+ * operations, constructors and notifications. The class
+ * name does not have to actually specify a valid class that
+ * can be loaded by the MBean server or class loader; it merely
+ * has to be a syntactically correct class name. Any of the
+ * arrays may be <code>null</code>; this will be treated as if
+ * an empty array was supplied. A copy of the arrays is
+ * taken, so later changes have no effect.
+ *
+ * @param name the name of the class this instance describes.
+ * @param desc a description of the bean.
+ * @param attribs the attribute descriptions for the bean,
+ * or <code>null</code>.
+ * @param cons the constructor descriptions for the bean,
+ * or <code>null</code>.
+ * @param ops the operation descriptions for the bean,
+ * or <code>null</code>.
+ * @param notifs the notification descriptions for the bean,
+ * or <code>null</code>.
+ * @throws ArrayStoreException if a members of an array
+ * is not assignable to the equivalent
+ * <code>MBeanXXXInfo</code> class.
+ */
+ public OpenMBeanInfoSupport(String name, String desc,
+ OpenMBeanAttributeInfo[] attribs,
+ OpenMBeanConstructorInfo[] cons,
+ OpenMBeanOperationInfo[] ops,
+ MBeanNotificationInfo[] notifs)
+ {
+ super(name, desc, (MBeanAttributeInfo[]) attribs,
+ (MBeanConstructorInfo[]) cons,
+ (MBeanOperationInfo[]) ops,
+ notifs);
+ }
+
+ /**
+ * Compares this attribute with the supplied object. This returns
+ * true iff the object is an instance of {@link OpenMBeanInfo}
+ * with the same class name and equal instances of the info classes.
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link OpenMBeanInfo}
+ * instance,
+ * <code>className.equals(object.getClassName())</code>
+ * and each info class has an equal in the other object.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof OpenMBeanInfo))
+ return false;
+ OpenMBeanInfo o = (OpenMBeanInfo) obj;
+ return getClassName().equals(o.getClassName()) &&
+ getAttributes().equals(o.getAttributes()) &&
+ getConstructors().equals(o.getConstructors()) &&
+ getNotifications().equals(o.getNotifications()) &&
+ getOperations().equals(o.getOperations());
+ }
+
+ /**
+ * <p>
+ * Returns the hashcode of the bean information as the sum of the
+ * hashcodes of the class name and each array (calculated using
+ * java.util.HashSet(<code>java.util.Arrays.asList(signature)).hashCode()</code>).
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return the hashcode of the bean information.
+ */
+ public int hashCode()
+ {
+ if (hashCode == null)
+ hashCode =
+ Integer.valueOf(getClassName().hashCode() +
+ new HashSet(Arrays.asList(getAttributes())).hashCode() +
+ new HashSet(Arrays.asList(getConstructors())).hashCode() +
+ new HashSet(Arrays.asList(getNotifications())).hashCode() +
+ new HashSet(Arrays.asList(getOperations())).hashCode());
+ return hashCode.intValue();
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.openmbean.OpenMBeanInfo</code>)
+ * along with the class name and textual representations
+ * of each array.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ string = getClass().getName()
+ + "[className=" + getClassName()
+ + ",attributes=" + Arrays.toString(getAttributes())
+ + ",constructors=" + Arrays.toString(getConstructors())
+ + ",notifications=" + Arrays.toString(getNotifications())
+ + ",operations=" + Arrays.toString(getOperations())
+ + "]";
+ return string;
+ }
+
+}
diff --git a/javax/management/openmbean/OpenMBeanOperationInfo.java b/javax/management/openmbean/OpenMBeanOperationInfo.java
new file mode 100644
index 000000000..8b61329d9
--- /dev/null
+++ b/javax/management/openmbean/OpenMBeanOperationInfo.java
@@ -0,0 +1,154 @@
+/* OpenMBeanOperationInfo.java -- Open typed info about a operation.
+ 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 javax.management.openmbean;
+
+import javax.management.MBeanParameterInfo;
+
+/**
+ * Describes a operation for an open management bean.
+ * This interface includes those methods specified by {@link
+ * javax.management.MBeanOperationInfo}, so implementations should
+ * extend this class. The {@link #getSignature()} method should
+ * return an array containing instances of {@link OpenMBeanParameterInfo}.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface OpenMBeanOperationInfo
+{
+
+ /**
+ * Compares this attribute with the supplied object. This returns
+ * true iff the object is an instance of {@link OpenMBeanOperationInfo}
+ * with an equal name, signature, open return type and impact.
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link OpenMBeanParameterInfo}
+ * instance,
+ * <code>name.equals(object.getName())</code>,
+ * <code>signature.equals(object.getSignature())</code>,
+ * <code>returnOpenType.equals(object.getReturnOpenType())</code>,
+ * and <code>impact == object.getImpact()</code>.
+ */
+ boolean equals(Object obj);
+
+ /**
+ * Returns a description of this operation.
+ *
+ * @return a human-readable description.
+ */
+ String getDescription();
+
+ /**
+ * <p>
+ * Returns the impact of performing this operation.
+ * The value is equal to one of the following:
+ * </p>
+ * <ol>
+ * <li>{@link javax.management.MBeanOperationInfo#INFO}
+ * &mdash; the method just returns
+ * information (akin to an accessor).</li>
+ * <li>{@link javax.management.MBeanOperationInfo#ACTION}
+ * the method just alters the state of the bean, without
+ * returning a value (akin to a mutator).</li>
+ * <li>{@link javax.management.MBeanOperationInfo#ACTION_INFO}
+ * the method both makes state changes and returns a value.</li>
+ * <li>{@link javax.management.MBeanOperationInfo#UNKNOWN}
+ * the behaviour of the operation is unknown.</li>
+ * </ol>
+ *
+ * @return the impact of performing the operation.
+ */
+ int getImpact();
+
+ /**
+ * Returns the name of this operation.
+ *
+ * @return the name of the operation.
+ */
+ String getName();
+
+ /**
+ * Returns the open type instance which represents the type of the
+ * return value.
+ *
+ * @return the open type of the return value.
+ */
+ OpenType getReturnOpenType();
+
+ /**
+ * Returns the return type of the operation, as the class
+ * name. This should be identical to
+ * <code>getReturnOpenType.getClassName()</code>.
+ *
+ * @return the return type.
+ */
+ String getReturnType();
+
+ /**
+ * Returns the operation's signature, in the form of
+ * information on each parameter. Each parameter is
+ * described by an instance of {@link OpenMBeanParameterInfo}.
+ *
+ * @return an array of {@link OpenMBeanParameterInfo} objects,
+ * describing the operation parameters.
+ */
+ MBeanParameterInfo[] getSignature();
+
+ /**
+ * Returns the hashcode of the operation information as the sum of
+ * the hashcodes of the name, open return type, impact and signature
+ * (calculated by
+ * <code>java.util.Arrays.asList(signature).hashCode()</code>).
+ *
+ * @return the hashcode of the operation information.
+ */
+ int hashCode();
+
+ /**
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.openmbean.OpenMBeanOperationInfo</code>)
+ * along with the name, signature, open return type and impact.
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ String toString();
+
+}
diff --git a/javax/management/openmbean/OpenMBeanOperationInfoSupport.java b/javax/management/openmbean/OpenMBeanOperationInfoSupport.java
new file mode 100644
index 000000000..07564897c
--- /dev/null
+++ b/javax/management/openmbean/OpenMBeanOperationInfoSupport.java
@@ -0,0 +1,240 @@
+/* OpenMBeanOperationInfoSupport.java -- Open typed info about an operation.
+ 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 javax.management.openmbean;
+
+import java.util.Arrays;
+
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+
+/**
+ * Describes a operation for an open management bean.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class OpenMBeanOperationInfoSupport
+ extends MBeanOperationInfo
+ implements OpenMBeanOperationInfo
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 4996859732565369366L;
+
+ /**
+ * The open type representing the return value.
+ */
+ private OpenType returnOpenType;
+
+ /**
+ * The hash code of this instance.
+ */
+ private transient Integer hashCode;
+
+ /**
+ * The <code>toString()</code> result of this instance.
+ */
+ private transient String string;
+
+ /**
+ * Constructs a @link{OpenMBeanOperationInfo} with the specified name,
+ * description, parameter information, open return type and impact. A
+ * <code>null</code> value for the parameter information is the same
+ * as passing in an empty array. A copy of the parameter array is
+ * taken, so later changes have no effect. The name and the
+ * description may not be equal to the empty string, and neither
+ * the name, description nor the open return type may be
+ * <code>null</code>. The value of <code>impact</code> must be
+ * one of the four valid values
+ * ({@link javax.management.MBeanOperationInfo#INFO},
+ * {@link javax.management.MBeanOperationInfo#ACTION},
+ * {@link javax.management.MBeanOperationInfo#ACTION_INFO} and
+ * {@link javax.management.MBeanOperationInfo#UNKNOWN}).
+ *
+ *
+ * @param name the name of the constructor.
+ * @param desc a description of the attribute.
+ * @param sig the signature of the method, as a series
+ * of {@link MBeanParameterInfo} objects, one for
+ * each parameter.
+ * @param type the open return type of the method.
+ * @param impact the impact of performing the operation.
+ * @throws IllegalArgumentException if the name, description or
+ * open return type is <code>null</code>,
+ * the name or description are equal to
+ * the empty string, or the impact factor
+ * is not one of the values enumerated
+ * above.
+ * @throws ArrayStoreException if the members of the signature array
+ * are not assignable to
+ * {@link javax.management.MBeanParameterInfo}
+ */
+ public OpenMBeanOperationInfoSupport(String name, String desc,
+ OpenMBeanParameterInfo[] sig,
+ OpenType type, int impact)
+ {
+ super(name, desc, (MBeanParameterInfo[]) sig,
+ type == null ? null : type.getClassName(), impact);
+ if (name == null)
+ throw new IllegalArgumentException("The name may not be null.");
+ if (desc == null)
+ throw new IllegalArgumentException("The description may not be null.");
+ if (type == null)
+ throw new IllegalArgumentException("The type may not be null.");
+ if (name.length() == 0)
+ throw new IllegalArgumentException("The name may not be the empty string.");
+ if (desc.length() == 0)
+ throw new IllegalArgumentException("The description may not be the " +
+ "empty string.");
+ if (impact != ACTION && impact != INFO &&
+ impact != ACTION_INFO && impact != UNKNOWN)
+ throw new IllegalArgumentException("The impact factor is an invalid value.");
+ returnOpenType = type;
+ }
+
+ /**
+ * Compares this attribute with the supplied object. This returns
+ * true iff the object is an instance of {@link OpenMBeanOperationInfo}
+ * with an equal name, signature, open return type and impact.
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link OpenMBeanParameterInfo}
+ * instance,
+ * <code>name.equals(object.getName())</code>,
+ * <code>signature.equals(object.getSignature())</code>,
+ * <code>returnOpenType.equals(object.getReturnOpenType())</code>,
+ * and <code>impact == object.getImpact()</code>.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof OpenMBeanOperationInfo))
+ return false;
+ OpenMBeanOperationInfo o = (OpenMBeanOperationInfo) obj;
+ return getName().equals(o.getName()) &&
+ getSignature().equals(o.getSignature()) &&
+ returnOpenType.equals(o.getReturnOpenType()) &&
+ getImpact() == o.getImpact();
+ }
+
+ /**
+ * Returns the open type instance which represents the type of the
+ * return value.
+ *
+ * @return the open type of the return value.
+ */
+ public OpenType getReturnOpenType()
+ {
+ return returnOpenType;
+ }
+
+ /**
+ * <p>
+ * Returns the hashcode of the operation information as the sum of
+ * the hashcodes of the name, open return type, impact and signature
+ * (calculated by
+ * <code>java.util.Arrays.asList(signature).hashCode()</code>).
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return the hashcode of the operation information.
+ */
+ public int hashCode()
+ {
+ if (hashCode == null)
+ hashCode = Integer.valueOf(getName().hashCode() +
+ returnOpenType.hashCode() +
+ Integer.valueOf(getImpact()).hashCode() +
+ Arrays.asList(getSignature()).hashCode());
+ return hashCode.intValue();
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.openmbean.OpenMBeanOperationInfo</code>)
+ * along with the name, signature, open return type and impact.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ {
+ String impactString;
+ switch (getImpact())
+ {
+ case INFO:
+ impactString = "INFO";
+ break;
+ case ACTION:
+ impactString = "ACTION";
+ break;
+ case ACTION_INFO:
+ impactString = "ACTION_INFO";
+ break;
+ case UNKNOWN:
+ impactString = "UNKNOWN";
+ break;
+ default:
+ impactString = "ERRONEOUS VALUE";
+ }
+ string = getClass().getName()
+ + "[name=" + getName()
+ + ",signature=" + Arrays.toString(getSignature())
+ + ",returnOpenType=" + returnOpenType
+ + ",impact=" + impactString
+ + "]";
+ }
+ return string;
+ }
+
+}
diff --git a/javax/management/openmbean/OpenMBeanParameterInfo.java b/javax/management/openmbean/OpenMBeanParameterInfo.java
new file mode 100644
index 000000000..780e8ba11
--- /dev/null
+++ b/javax/management/openmbean/OpenMBeanParameterInfo.java
@@ -0,0 +1,190 @@
+/* OpenMBeanParameterInfo.java -- Open typed info about a parameter.
+ 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 javax.management.openmbean;
+
+import java.util.Set;
+
+/**
+ * Describes the parameters of a constructor or operation associated
+ * with an open management bean. This interface includes those methods
+ * specified by {@link javax.management.MBeanParameterInfo}, so
+ * implementations should extend this class.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface OpenMBeanParameterInfo
+{
+
+ /**
+ * Compares this parameter with the supplied object. This returns
+ * true iff the object is an instance of {@link OpenMBeanParameterInfo}
+ * with an equal name and open type and the same default, minimum,
+ * maximum and legal values.
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link OpenMBeanParameterInfo}
+ * instance,
+ * <code>name.equals(object.getName())</code>,
+ * <code>openType.equals(object.getOpenType())</code>,
+ * <code>defaultValue.equals(object.getDefaultValue())</code>,
+ * <code>minValue.equals(object.getMinValue())</code>,
+ * <code>maxValue.equals(object.getMaxValue())</code>,
+ * and <code>legalValues.equals(object.getLegalValues())</code>.
+ */
+ boolean equals(Object obj);
+
+ /**
+ * Returns the default value of this parameter, or <code>null</code>
+ * if there is no default value.
+ *
+ * @return the default value of the parameter, or <code>null</code>
+ * if there is no default.
+ */
+ Object getDefaultValue();
+
+ /**
+ * Returns a description of this parameter.
+ *
+ * @return a human-readable description.
+ */
+ String getDescription();
+
+ /**
+ * Returns a {@link java.util.Set} enumerating the legal values
+ * of this parameter, or <code>null</code> if no such limited
+ * set exists for this parameter.
+ *
+ * @return a set of legal values, or <code>null</code> if no such
+ * set exists.
+ */
+ Set getLegalValues();
+
+ /**
+ * Returns the maximum value of this parameter, or <code>null</code>
+ * if there is no maximum.
+ *
+ * @return the maximum value, or <code>null</code> if none exists.
+ */
+ Comparable getMaxValue();
+
+ /**
+ * Returns the minimum value of this parameter, or <code>null</code>
+ * if there is no minimum.
+ *
+ * @return the minimum value, or <code>null</code> if none exists.
+ */
+ Comparable getMinValue();
+
+ /**
+ * Returns the name of this parameter.
+ *
+ * @return the name of the parameter.
+ */
+ String getName();
+
+ /**
+ * Returns the open type instance which represents the type of this
+ * parameter.
+ *
+ * @return the open type of this parameter.
+ */
+ OpenType getOpenType();
+
+ /**
+ * Returns true if this parameter has a default value.
+ *
+ * @return true if this parameter has a default.
+ */
+ boolean hasDefaultValue();
+
+ /**
+ * Returns the hashcode of the parameter information as the sum of
+ * the hashcodes of the name, open type, default value, maximum
+ * value, minimum value and the set of legal values.
+ *
+ * @return the hashcode of the parameter information.
+ */
+ int hashCode();
+
+ /**
+ * Returns true if there is a set of legal values for this
+ * parameter.
+ *
+ * @return true if a set of legal values exists for this
+ * parameter.
+ */
+ boolean hasLegalValues();
+
+ /**
+ * Returns true if there is a maximum value for this parameter.
+ *
+ * @return true if a maximum value exists for this parameter.
+ */
+ boolean hasMaxValue();
+
+ /**
+ * Returns true if there is a minimum value for this parameter.
+ *
+ * @return true if a minimum value exists for this parameter.
+ */
+ boolean hasMinValue();
+
+ /**
+ * Returns true if the specified object is a valid value for
+ * this parameter.
+ *
+ * @param obj the object to test.
+ * @return true if <code>obj</code> is a valid value for this
+ * parameter.
+ */
+ boolean isValue(Object obj);
+
+ /**
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.openmbean.OpenMBeanParameterInfo</code>)
+ * along with the name, open type, default, minimum, maximum
+ * and legal values of the parameter.
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ String toString();
+
+}
diff --git a/javax/management/openmbean/OpenMBeanParameterInfoSupport.java b/javax/management/openmbean/OpenMBeanParameterInfoSupport.java
new file mode 100644
index 000000000..af3bda6c7
--- /dev/null
+++ b/javax/management/openmbean/OpenMBeanParameterInfoSupport.java
@@ -0,0 +1,511 @@
+/* OpenMBeanParameterInfoSupport.java -- Open typed info about a parameter.
+ 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 javax.management.openmbean;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.management.MBeanParameterInfo;
+
+/**
+ * Describes the parameters of a constructor or operation associated
+ * with an open management bean.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class OpenMBeanParameterInfoSupport
+ extends MBeanParameterInfo
+ implements OpenMBeanParameterInfo
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -7235016873758443122L;
+
+ /**
+ * The open type of the parameter.
+ */
+ private OpenType openType;
+
+ /**
+ * The default value of the parameter (may be <code>null</code>).
+ */
+ private Object defaultValue;
+
+ /**
+ * The possible legal values of the parameter (may be <code>null</code>).
+ */
+ private Set legalValues;
+
+ /**
+ * The minimum value of the parameter (may be <code>null</code>).
+ */
+ private Comparable minValue;
+
+ /**
+ * The maximum value of the parameter (may be <code>null</code>).
+ */
+ private Comparable maxValue;
+
+ /**
+ * The hash code of this instance.
+ */
+ private transient Integer hashCode;
+
+ /**
+ * The <code>toString()</code> result of this instance.
+ */
+ private transient String string;
+
+ /**
+ * Constructs a new {@link OpenMBeanParameterInfo} using the specified
+ * name, description and open type. None of these values may be
+ * <code>null</code> and the name and description may not be equal
+ * to the empty string.
+ *
+ * @param name the name of the parameter.
+ * @param desc a description of the parameter.
+ * @param type the open type of the parameter.
+ * @throws IllegalArgumentException if the name, description or
+ * open type are <code>null</code>
+ * or the name or description are
+ * the empty string.
+ */
+ public OpenMBeanParameterInfoSupport(String name, String desc, OpenType type)
+ {
+ super(name, type == null ? null : type.getClassName(), desc);
+ if (name == null)
+ throw new IllegalArgumentException("The name may not be null.");
+ if (desc == null)
+ throw new IllegalArgumentException("The description may not be null.");
+ if (type == null)
+ throw new IllegalArgumentException("The type may not be null.");
+ if (name.length() == 0)
+ throw new IllegalArgumentException("The name may not be the empty string.");
+ if (desc.length() == 0)
+ throw new IllegalArgumentException("The description may not be the " +
+ "empty string.");
+ openType = type;
+ }
+
+ /**
+ * Constructs a new {@link OpenMBeanParameterInfo} using the
+ * specified name, description, open type and default value. The
+ * name, description and open type cannot be <code>null</code> and
+ * the name and description may not be equal to the empty string.
+ * The default value may be <code>null</code>. If non-null, it must
+ * be a valid value of the given open type. Default values are not
+ * applicable to the open types, {@link ArrayType} and {@link
+ * TabularType}.
+ *
+ * @param name the name of the parameter.
+ * @param desc a description of the parameter.
+ * @param type the open type of the parameter.
+ * @param defaultValue the default value of the parameter.
+ * @throws IllegalArgumentException if the name, description or
+ * open type are <code>null</code>
+ * or the name or description are
+ * the empty string.
+ * @throws OpenDataException if <code>defaultValue<code> is non-null
+ * and is either not a value of the given
+ * open type or the open type is an instance
+ * of {@link ArrayType} or {@link TabularType}.
+ */
+ public OpenMBeanParameterInfoSupport(String name, String desc, OpenType type,
+ Object defaultValue)
+ throws OpenDataException
+ {
+ this(name, desc, type, defaultValue, null);
+ }
+
+ /**
+ * <p>
+ * Constructs a new {@link OpenMBeanParameterInfo} using the
+ * specified name, description, open type, default, maximum and
+ * minimum values. The name, description and open type cannot be
+ * <code>null</code> and the name and description may not be equal
+ * to the empty string. The default, maximum and minimum values may
+ * be <code>null</code>. The following conditions apply when the
+ * parameters mentioned are non-null:
+ * </p>
+ * <ul>
+ * <li>The values must be valid values for the given open type.</li>
+ * <li>Default values are not applicable to the open types, {@link
+ * ArrayType} and {@link TabularType}.</li>
+ * <li>The minimum value must be smaller than or equal to the maximum value
+ * (literally, <code>minValue.compareTo(maxValue) <= 0</code>.</li>
+ * <li>The minimum value must be smaller than or equal to the default value
+ * (literally, <code>minValue.compareTo(defaultValue) <= 0</code>.</li>
+ * <li>The default value must be smaller than or equal to the maximum value
+ * (literally, <code>defaultValue.compareTo(maxValue) <= 0</code>.</li>
+ * </ul>
+ *
+ * @param name the name of the parameter.
+ * @param desc a description of the parameter.
+ * @param type the open type of the parameter.
+ * @param defaultValue the default value of the parameter, or <code>null</code>.
+ * @param minimumValue the minimum value of the parameter, or <code>null</code>.
+ * @param maximumValue the maximum value of the parameter, or <code>null</code>.
+ * @throws IllegalArgumentException if the name, description or
+ * open type are <code>null</code>
+ * or the name or description are
+ * the empty string.
+ * @throws OpenDataException if any condition in the list above is broken.
+ */
+ public OpenMBeanParameterInfoSupport(String name, String desc, OpenType type,
+ Object defaultValue, Comparable minimumValue,
+ Comparable maximumValue)
+ throws OpenDataException
+ {
+ this(name, desc, type);
+ if (defaultValue != null && !(type.isValue(defaultValue)))
+ throw new OpenDataException("The default value is not a member of the " +
+ "open type given.");
+ if (minimumValue != null && !(type.isValue(minimumValue)))
+ throw new OpenDataException("The minimum value is not a member of the " +
+ "open type given.");
+ if (maximumValue != null && !(type.isValue(maximumValue)))
+ throw new OpenDataException("The maximum value is not a member of the " +
+ "open type given.");
+ if (defaultValue != null && (type instanceof ArrayType ||
+ type instanceof TabularType))
+ throw new OpenDataException("Default values are not applicable for " +
+ "array or tabular types.");
+ if (minValue != null && maxValue != null
+ && minValue.compareTo(maxValue) > 0)
+ throw new OpenDataException("The minimum value is greater than the " +
+ "maximum.");
+ if (minValue != null && defaultValue != null
+ && minValue.compareTo(defaultValue) > 0)
+ throw new OpenDataException("The minimum value is greater than the " +
+ "default.");
+ if (defaultValue != null && maxValue != null
+ && maxValue.compareTo(defaultValue) < 0)
+ throw new OpenDataException("The default value is greater than the " +
+ "maximum.");
+
+ this.defaultValue = defaultValue;
+ minValue = minimumValue;
+ maxValue = maximumValue;
+ }
+
+ /**
+ * <p>
+ * Constructs a new {@link OpenMBeanParameterInfo} using the
+ * specified name, description, open type, default value and
+ * set of legal values. The name, description and open type cannot be
+ * <code>null</code> and the name and description may not be equal
+ * to the empty string. The default, maximum and minimum values may
+ * be <code>null</code>. The following conditions apply when the
+ * parameters mentioned are non-null:
+ * </p>
+ * <ul>
+ * <li>The default value and each of the legal values must be a valid
+ * value for the given open type.</li>
+ * <li>Default and legal values are not applicable to the open types, {@link
+ * ArrayType} and {@link TabularType}.</li>
+ * <li>The default value is not in the set of legal values.</li>
+ * </ul>
+ * <p>
+ * The legal values are copied from the array into a unmodifiable set,
+ * so future modifications to the array have no effect.
+ * </p>
+ *
+ * @param name the name of the parameter.
+ * @param desc a description of the parameter.
+ * @param type the open type of the parameter.
+ * @param defaultValue the default value of the parameter, or <code>null</code>.
+ * @param legalValues the legal values of the parameter. May be
+ * <code>null</code> or an empty array.
+ * @throws IllegalArgumentException if the name, description or
+ * open type are <code>null</code>
+ * or the name or description are
+ * the empty string.
+ * @throws OpenDataException if any condition in the list above is broken.
+ */
+ public OpenMBeanParameterInfoSupport(String name, String desc, OpenType type,
+ Object defaultValue, Object[] legalValues)
+ throws OpenDataException
+ {
+ this(name, desc, type);
+ if (defaultValue != null && !(type.isValue(defaultValue)))
+ throw new OpenDataException("The default value is not a member of the " +
+ "open type given.");
+ if (defaultValue != null && (type instanceof ArrayType ||
+ type instanceof TabularType))
+ throw new OpenDataException("Default values are not applicable for " +
+ "array or tabular types.");
+ if (legalValues != null && (type instanceof ArrayType ||
+ type instanceof TabularType))
+ throw new OpenDataException("Legal values are not applicable for " +
+ "array or tabular types.");
+ if (legalValues != null && legalValues.length > 0)
+ {
+ Set lv = new HashSet(legalValues.length);
+ for (int a = 0; a < legalValues.length; ++a)
+ {
+ if (legalValues[a] != null &&
+ !(type.isValue(legalValues[a])))
+ throw new OpenDataException("The legal value, "
+ + legalValues[a] +
+ "is not a member of the " +
+ "open type given.");
+ lv.add(legalValues[a]);
+ }
+ if (defaultValue != null && !(lv.contains(defaultValue)))
+ throw new OpenDataException("The default value is not in the set " +
+ "of legal values.");
+ this.legalValues = Collections.unmodifiableSet(lv);
+ }
+ this.defaultValue = defaultValue;
+ }
+
+ /**
+ * Compares this parameter with the supplied object. This returns
+ * true iff the object is an instance of {@link OpenMBeanParameterInfo}
+ * with an equal name and open type and the same default, minimum,
+ * maximum and legal values.
+ *
+ * @param obj the object to compare.
+ * @return true if the object is a {@link OpenMBeanParameterInfo}
+ * instance,
+ * <code>name.equals(object.getName())</code>,
+ * <code>openType.equals(object.getOpenType())</code>,
+ * <code>defaultValue.equals(object.getDefaultValue())</code>,
+ * <code>minValue.equals(object.getMinValue())</code>,
+ * <code>maxValue.equals(object.getMaxValue())</code>,
+ * and <code>legalValues.equals(object.getLegalValues())</code>.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof OpenMBeanParameterInfo))
+ return false;
+ OpenMBeanParameterInfo o = (OpenMBeanParameterInfo) obj;
+ return getName().equals(o.getName()) &&
+ openType.equals(o.getOpenType()) &&
+ (defaultValue == null ? o.getDefaultValue() == null :
+ defaultValue.equals(o.getDefaultValue())) &&
+ (minValue == null ? o.getMinValue() == null :
+ minValue.equals(o.getMinValue())) &&
+ (maxValue == null ? o.getMaxValue() == null :
+ maxValue.equals(o.getMaxValue())) &&
+ (legalValues == null ? o.getLegalValues() == null :
+ legalValues.equals(o.getLegalValues()));
+ }
+
+ /**
+ * Returns the default value of this parameter, or <code>null</code>
+ * if there is no default value.
+ *
+ * @return the default value of the parameter, or <code>null</code>
+ * if there is no default.
+ */
+ public Object getDefaultValue()
+ {
+ return defaultValue;
+ }
+
+ /**
+ * Returns a {@link java.util.Set} enumerating the legal values
+ * of this parameter, or <code>null</code> if no such limited
+ * set exists for this parameter.
+ *
+ * @return a set of legal values, or <code>null</code> if no such
+ * set exists.
+ */
+ public Set getLegalValues()
+ {
+ return legalValues;
+ }
+
+ /**
+ * Returns the maximum value of this parameter, or <code>null</code>
+ * if there is no maximum.
+ *
+ * @return the maximum value, or <code>null</code> if none exists.
+ */
+ public Comparable getMaxValue()
+ {
+ return maxValue;
+ }
+
+ /**
+ * Returns the minimum value of this parameter, or <code>null</code>
+ * if there is no minimum.
+ *
+ * @return the minimum value, or <code>null</code> if none exists.
+ */
+ public Comparable getMinValue()
+ {
+ return minValue;
+ }
+
+ /**
+ * Returns the open type instance which represents the type of this
+ * parameter.
+ *
+ * @return the open type of this parameter.
+ */
+ public OpenType getOpenType()
+ {
+ return openType;
+ }
+
+ /**
+ * Returns true if this parameter has a default value
+ * (i.e. the value is non-null).
+ *
+ * @return true if this parameter has a default.
+ */
+ public boolean hasDefaultValue()
+ {
+ return defaultValue != null;
+ }
+
+ /**
+ * <p>
+ * Returns the hashcode of the parameter information as the sum of
+ * the hashcodes of the name, open type, default value, maximum
+ * value, minimum value and the set of legal values.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the hash code
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return the hashcode of the parameter information.
+ */
+ public int hashCode()
+ {
+ if (hashCode == null)
+ hashCode = Integer.valueOf(getName().hashCode() +
+ openType.hashCode() +
+ (defaultValue == null ? 0 :
+ defaultValue.hashCode()) +
+ (minValue == null ? 0 :
+ minValue.hashCode()) +
+ (maxValue == null ? 0 :
+ maxValue.hashCode()) +
+ (legalValues == null ? 0 :
+ legalValues.hashCode()));
+ return hashCode.intValue();
+ }
+
+ /**
+ * Returns true if there is a set of legal values for this
+ * parameter (i.e. the value is non-null).
+ *
+ * @return true if a set of legal values exists for this
+ * parameter.
+ */
+ public boolean hasLegalValues()
+ {
+ return legalValues != null;
+ }
+
+ /**
+ * Returns true if there is a maximum value for this parameter
+ * (i.e. the value is non-null).
+ *
+ * @return true if a maximum value exists for this parameter.
+ */
+ public boolean hasMaxValue()
+ {
+ return maxValue != null;
+ }
+
+ /**
+ * Returns true if there is a minimum value for this parameter.
+ * (i.e. the value is non-null).
+ *
+ * @return true if a minimum value exists for this parameter.
+ */
+ public boolean hasMinValue()
+ {
+ return minValue != null;
+ }
+
+ /**
+ * Returns true if the specified object is a valid value for
+ * this parameter.
+ *
+ * @param obj the object to test.
+ * @return true if <code>obj</code> is a valid value for this
+ * parameter.
+ */
+ public boolean isValue(Object obj)
+ {
+ return openType.isValue(obj);
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.openmbean.OpenMBeanParameterInfo</code>)
+ * along with the name, open type, default, minimum, maximum
+ * and legal values of the parameter.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ string = getClass().getName()
+ + "[name=" + getName()
+ + ",openType=" + openType
+ + ",defaultValue=" + defaultValue
+ + ",minValue=" + minValue
+ + ",maxValue=" + maxValue
+ + ",legalValues=" + legalValues
+ + "]";
+ return string;
+ }
+
+}
diff --git a/javax/management/openmbean/OpenType.java b/javax/management/openmbean/OpenType.java
new file mode 100644
index 000000000..b08c40ccc
--- /dev/null
+++ b/javax/management/openmbean/OpenType.java
@@ -0,0 +1,230 @@
+/* OpenType.java -- Superclass of all open types.
+ 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 javax.management.openmbean;
+
+import java.io.Serializable;
+
+/**
+ * The superclass of all open types, which describe the
+ * applicable data values for open MBeans. An open type
+ * is defined by its name and description, and the name
+ * of the Java class it maps to.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public abstract class OpenType
+ implements Serializable
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -9195195325186646468L;
+
+ /**
+ * The name of the Java class this type represents.
+ */
+ private String className;
+
+ /**
+ * The name of this type.
+ */
+ private String typeName;
+
+ /**
+ * A description of this type.
+ */
+ private String description;
+
+ /**
+ * An array which defines the set of Java types which can be
+ * used as open types. Note that each type is also available
+ * in array form, possibly with multiple dimensions.
+ */
+ public static final String[] ALLOWED_CLASSNAMES = {
+ "java.lang.Void",
+ "java.lang.Boolean",
+ "java.lang.Character",
+ "java.lang.Byte",
+ "java.lang.Short",
+ "java.lang.Integer",
+ "java.lang.Long",
+ "java.lang.Float",
+ "java.lang.Double",
+ "java.lang.String",
+ "java.math.BigDecimal",
+ "java.math.BigInteger",
+ "java.util.Date",
+ "javax.management.ObjectName",
+ CompositeData.class.getName(),
+ TabularData.class.getName()
+ };
+
+ /**
+ * Constructs a new {@link OpenType} for the specified class
+ * with the given name and description. The name of the class
+ * must be taken from the list of {@link ALLOWED_CLASSNAMES}.
+ * Arrays are implictly included in this, and follow the usual
+ * syntax of {@link java.lang.Class#getName()} with the name
+ * preceded by n instances of '[' (where n is the number of
+ * dimensions) and an L. The name and description can not be
+ * <code>null</code> or the empty string.
+ *
+ * @param className the name of the Java class this type
+ * represents.
+ * @param name the name of the type.
+ * @param desc the description of the type.
+ * @throws IllegalArgumentException if either of <code>name</code>
+ * or <code>desc</code> are
+ * <code>null</code> or the empty
+ * string.
+ * @throws OpenDataException if the class name does not reference
+ * a listed class (from @{link ALLOWED_CLASSNAMES})
+ */
+ protected OpenType(String className, String name, String desc)
+ throws OpenDataException
+ {
+ if (name == null || name.equals(""))
+ throw new IllegalArgumentException("The name can not be null " +
+ "or the empty string.");
+ if (desc == null || desc.equals(""))
+ throw new IllegalArgumentException("The description can not " +
+ "be null or the empty string.");
+ String testString;
+ if (className.startsWith("["))
+ testString = className.substring(className.indexOf("L") + 1);
+ else
+ testString = className;
+ boolean openTypeFound = false;
+ for (int a = 0; a < ALLOWED_CLASSNAMES.length; ++a)
+ if (ALLOWED_CLASSNAMES[a].equals(className))
+ openTypeFound = true;
+ if (!openTypeFound)
+ throw new OpenDataException("The class name does not specify " +
+ "a valid open type.");
+ this.className = className;
+ typeName = name;
+ description = desc;
+ }
+
+ /**
+ * Performs an equality test on this object and the one specified.
+ *
+ * @param obj the object to test against this one.
+ * @return true if the two objects are equivalent.
+ * @see java.lang.Object#hashCode()
+ */
+ public abstract boolean equals(Object obj);
+
+ /**
+ * Returns the name of the Java class this type represents. This must
+ * be one of the {@link ALLOWED_CLASSNAMES} or an array of one of them.
+ * The specification of arrays follows the standard set by
+ * {@link java.lang.Class#getName()} i.e. the name is the class name
+ * preceded by n instances of '[' and an 'L', where n is number of
+ * dimensions used by the array.
+ *
+ * @return the class name.
+ */
+ public String getClassName()
+ {
+ return className;
+ }
+
+ /**
+ * Returns a description of this open type.
+ *
+ * @return the description.
+ */
+ public String getDescription()
+ {
+ return description;
+ }
+
+ /**
+ * Returns the name of this open type.
+ *
+ * @return the type name.
+ */
+ public String getTypeName()
+ {
+ return typeName;
+ }
+
+ /**
+ * Returns a hash code for this open type. The hash code
+ * should be consistent with the {@link equals()} method.
+ * Thus, it should continue to return the same value while
+ * the values used by the {@link equals()} method remain
+ * the same, and should return different hash codes for
+ * objects which are judged to be different using the
+ * {@link equals()} method.
+ *
+ * @return the hash code of this instance.
+ */
+ public abstract int hashCode();
+
+ /**
+ * Returns true if this open type represents an array type.
+ *
+ * @return true if this open type represents an array type.
+ */
+ public boolean isArray()
+ {
+ return className.startsWith("[");
+ }
+
+ /**
+ * Returns true if the specified object is a member of this
+ * type.
+ *
+ * @param obj the object to test for membership.
+ * @return true if the object is a member of this type.
+ */
+ public abstract boolean isValue(Object obj);
+
+ /**
+ * Returns a textual representation of this type.
+ *
+ * @return a {@link java.lang.String} representation of this
+ * type.
+ */
+ public abstract String toString();
+
+}
diff --git a/javax/management/openmbean/SimpleType.java b/javax/management/openmbean/SimpleType.java
new file mode 100644
index 000000000..39753f1c6
--- /dev/null
+++ b/javax/management/openmbean/SimpleType.java
@@ -0,0 +1,342 @@
+/* SimpleType.java -- Open type descriptor for the base types.
+ 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 javax.management.openmbean;
+
+import java.io.InvalidObjectException;
+import java.io.ObjectStreamException;
+
+/**
+ * The open type descriptor for data values that are members
+ * of one of the simple types (such as an integer or a string).
+ * The other open types ({@link ArrayType}, {@link CompositeType},
+ * {@link TabularType}) are constructed from one or more of these
+ * types. The simple types are formed from a small subset of
+ * basic Java types. As a result, the valid instances of this
+ * class are predefined, and no constructor is given for creating
+ * new instances.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public final class SimpleType
+ extends OpenType
+{
+
+ /**
+ * The {@link SimpleType} representation of
+ * <code>java.math.BigDecimal</code>.
+ */
+ public static final SimpleType BIGDECIMAL;
+
+ /**
+ * The {@link SimpleType} representation of
+ * <code>java.math.BigInteger</code>.
+ */
+ public static final SimpleType BIGINTEGER;
+
+ /**
+ * The {@link SimpleType} representation of
+ * <code>java.lang.Boolean</code>.
+ */
+ public static final SimpleType BOOLEAN;
+
+ /**
+ * The {@link SimpleType} representation of
+ * <code>java.lang.Byte</code>.
+ */
+ public static final SimpleType BYTE;
+
+ /**
+ * The {@link SimpleType} representation of
+ * <code>java.lang.Character</code>.
+ */
+ public static final SimpleType CHARACTER;
+
+ /**
+ * The {@link SimpleType} representation of
+ * <code>java.util.Date</code>.
+ */
+ public static final SimpleType DATE;
+
+ /**
+ * The {@link SimpleType} representation of
+ * <code>java.lang.Double</code>.
+ */
+ public static final SimpleType DOUBLE;
+
+ /**
+ * The {@link SimpleType} representation of
+ * <code>java.lang.Float</code>.
+ */
+ public static final SimpleType FLOAT;
+
+ /**
+ * The {@link SimpleType} representation of
+ * <code>java.lang.Integer</code>.
+ */
+ public static final SimpleType INTEGER;
+
+ /**
+ * The {@link SimpleType} representation of
+ * <code>java.lang.Long</code>.
+ */
+ public static final SimpleType LONG;
+
+ /**
+ * The {@link SimpleType} representation of
+ * <code>javax.management.ObjectName</code>.
+ */
+ public static final SimpleType OBJECTNAME;
+
+
+ /**
+ * The {@link SimpleType} representation of
+ * <code>java.lang.Short</code>.
+ */
+ public static final SimpleType SHORT;
+
+ /**
+ * The {@link SimpleType} representation of
+ * <code>java.lang.String</code>.
+ */
+ public static final SimpleType STRING;
+
+ /**
+ * The {@link SimpleType} representation of
+ * <code>java.lang.Void</code>.
+ */
+ public static final SimpleType VOID;
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 2215577471957694503L;
+
+ /**
+ * The hash code of this instance.
+ */
+ private transient Integer hashCode;
+
+ /**
+ * The <code>toString()</code> result of this instance.
+ */
+ private transient String string;
+
+ /**
+ * Static construction of the {@link SimpleType} instances.
+ */
+ static
+ {
+ try
+ {
+ BIGDECIMAL = new SimpleType("java.math.BigDecimal");
+ BIGINTEGER = new SimpleType("java.math.BigInteger");
+ BOOLEAN = new SimpleType("java.lang.Boolean");
+ BYTE = new SimpleType("java.lang.Byte");
+ CHARACTER = new SimpleType("java.lang.Character");
+ DATE = new SimpleType("java.util.Date");
+ DOUBLE = new SimpleType("java.lang.Double");
+ FLOAT = new SimpleType("java.lang.Float");
+ INTEGER = new SimpleType("java.lang.Integer");
+ LONG = new SimpleType("java.lang.Long");
+ OBJECTNAME = new SimpleType("javax.management.ObjectName");
+ SHORT = new SimpleType("java.lang.Short");
+ STRING = new SimpleType("java.lang.String");
+ VOID = new SimpleType("java.lang.Void");
+ }
+ catch (OpenDataException e)
+ {
+ /* In normal circumstances, this shouldn't be possible. */
+ throw new IllegalStateException("A invalid class name " +
+ "was passed to the SimpleType " +
+ "constructor.");
+ }
+ }
+
+ /**
+ * Constructs a new {@link SimpleType} instance for the given
+ * class name. The class name is also used as the type name
+ * and description of the {@link OpenType} instance.
+ *
+ * @param name the name of the class this instance should
+ * represent.
+ * @throws OpenDataException if somehow the constructor of the
+ * superclass is passed an invalid
+ * class name.
+ */
+ private SimpleType(String name)
+ throws OpenDataException
+ {
+ super(name, name, name);
+ }
+
+ /**
+ * <p>
+ * Compares this simple data type with another object
+ * for equality. The objects are judged to be equal if:
+ * </p>
+ * <ul>
+ * <li><code>obj</code> is not null.</li>
+ * <li><code>obj</code> is an instance of
+ * {@link SimpleType}.</li>
+ * <li>The class names are equal.</li>
+ * </ul>
+ *
+ * @param obj the object to compare with.
+ * @return true if the conditions above hold.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof SimpleType))
+ return false;
+ SimpleType sType = (SimpleType) obj;
+ return sType.getClassName().equals(getClassName());
+ }
+
+ /**
+ * <p>
+ * Returns the hash code of the simple data type.
+ * This is simply the hash code of the class name,
+ * which is the same element of the type compared
+ * as part of the
+ * {@link #equals(java.lang.Object)} method, thus ensuring
+ * that the hashcode is compatible with the equality
+ * test.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the hash code
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return the hash code of this instance.
+ */
+ public int hashCode()
+ {
+ if (hashCode == null)
+ hashCode = Integer.valueOf(getClassName().hashCode());
+ return hashCode.intValue();
+ }
+
+ /**
+ * Returns true if the specified object is a member of this
+ * simple type. The object is judged to be so if it is
+ * non-null and its class name is the same as that returned
+ * by {@link SimpleType#getClassName()}.
+ *
+ * @param obj the object to test for membership.
+ * @return true if the object is a member of this type.
+ */
+ public boolean isValue(Object obj)
+ {
+ if (obj == null)
+ return false;
+ return obj.getClass().getName().equals(getClassName());
+ }
+
+ /**
+ * Replaces instances of this class read from an
+ * {@link java.io.ObjectInputStream} with one of the predefined
+ * values. This ensures that each existing instance of
+ * this class is one of these unique instances.
+ *
+ * @return the replacement object.
+ * @throws ObjectStreamException if the object can not be
+ * resolved.
+ */
+ public Object readResolve()
+ throws ObjectStreamException
+ {
+ if (equals(BIGDECIMAL))
+ return BIGDECIMAL;
+ if (equals(BIGINTEGER))
+ return BIGINTEGER;
+ if (equals(BOOLEAN))
+ return BOOLEAN;
+ if (equals(BYTE))
+ return BYTE;
+ if (equals(CHARACTER))
+ return CHARACTER;
+ if (equals(DATE))
+ return DATE;
+ if (equals(DOUBLE))
+ return DOUBLE;
+ if (equals(FLOAT))
+ return FLOAT;
+ if (equals(INTEGER))
+ return INTEGER;
+ if (equals(LONG))
+ return LONG;
+ if (equals(OBJECTNAME))
+ return OBJECTNAME;
+ if (equals(SHORT))
+ return SHORT;
+ if (equals(STRING))
+ return STRING;
+ if (equals(VOID))
+ return VOID;
+ throw new InvalidObjectException("Invalid simple type instance " +
+ "deserialized.");
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.openmbean.SimpleType</code>)
+ * and the name of the class the type represents.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ string = getClass().getName()
+ + "[name=" + getClassName()
+ + "]";
+ return string;
+ }
+
+}
diff --git a/javax/management/openmbean/TabularData.java b/javax/management/openmbean/TabularData.java
new file mode 100644
index 000000000..7e57e0fd8
--- /dev/null
+++ b/javax/management/openmbean/TabularData.java
@@ -0,0 +1,259 @@
+/* TabularData.java -- Tables of composite data structures.
+ 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 javax.management.openmbean;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * Provides an interface to a specific type of composite
+ * data structure, where keys (the columns) map to the
+ * {@link CompositeData} objects that form the rows of
+ * the table.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface TabularData
+{
+
+ /**
+ * Calculates the index the specified {@link CompositeData} value
+ * would have, if it was to be added to this {@link TabularData}
+ * instance. This method includes a check that the type of the
+ * given value is the same as the row type of this instance, but not
+ * a check for existing instances of the given value. The value
+ * must also not be <code>null</code>. Possible indices are
+ * returned by the {@link TabularType#getIndexNames()} method of
+ * this instance's tabular type. The returned indices are the
+ * values of the fields in the supplied {@link CompositeData}
+ * instance that match the names given in the {@link TabularType}.
+ *
+ * @param val the {@link CompositeData} value whose index should
+ * be calculated.
+ * @return the index the value would take on, if it were to be added.
+ * @throws NullPointerException if the value is <code>null</code>.
+ * @throws InvalidOpenTypeException if the value does not match the
+ * row type of this instance.
+ */
+ Object[] calculateIndex(CompositeData val);
+
+ /**
+ * Removes all {@link CompositeData} values from the table.
+ */
+ void clear();
+
+ /**
+ * Returns true iff this instance of the {@link TabularData} class
+ * contains a {@link CompositeData} value at the specified index.
+ * In any other circumstance, including if the given key
+ * is <code>null</code> or of the incorrect type, according to
+ * the {@link TabularType} of this instance, this method returns
+ * false.
+ *
+ * @param key the key to test for.
+ * @return true if the key maps to a {@link CompositeData} value.
+ */
+ boolean containsKey(Object[] key);
+
+ /**
+ * Returns true iff this instance of the {@link TabularData} class
+ * contains the specified {@link CompositeData} value.
+ * In any other circumstance, including if the given value
+ * is <code>null</code> or of the incorrect type, according to
+ * the {@link TabularType} of this instance, this method returns
+ * false.
+ *
+ * @param val the value to test for.
+ * @return true if the value exists.
+ */
+ boolean containsValue(CompositeData val);
+
+ /**
+ * Compares the specified object with this object for equality.
+ * The object is judged equivalent if it is non-null, and also
+ * an instance of {@link TabularData} with the same row type,
+ * and {@link CompositeData} values. The two compared instances may
+ * be equivalent even if they represent different implementations
+ * of {@link TabularData}.
+ *
+ * @param obj the object to compare for equality.
+ * @return true if <code>obj</code> is equal to <code>this</code>.
+ */
+ boolean equals(Object obj);
+
+ /**
+ * Retrieves the {@link CompositeData} value for the specified
+ * key, or <code>null</code> if no such mapping exists.
+ *
+ * @param key the key whose value should be returned.
+ * @return the matching {@link CompositeData} value, or
+ * <code>null</code> if one does not exist.
+ * @throws NullPointerException if the key is <code>null</code>.
+ * @throws InvalidKeyException if the key does not match
+ * the {@link TabularType} of this
+ * instance.
+ */
+ CompositeData get(Object[] key);
+
+ /**
+ * Returns the tabular type which corresponds to this instance
+ * of {@link TabularData}.
+ *
+ * @return the tabular type for this instance.
+ */
+ TabularType getTabularType();
+
+ /**
+ * Returns the hash code of the composite data type. This is
+ * computed as the sum of the hash codes of each value, together
+ * with the hash code of the tabular type. These are the same
+ * elements of the type that are compared as part of the {@link
+ * #equals(java.lang.Object)} method, thus ensuring that the
+ * hashcode is compatible with the equality test.
+ *
+ * @return the hash code of this instance.
+ */
+ int hashCode();
+
+ /**
+ * Returns true if this {@link TabularData} instance
+ * contains no {@link CompositeData} values.
+ *
+ * @return true if the instance is devoid of rows.
+ */
+ boolean isEmpty();
+
+ /**
+ * Returns a {@link java.util.Set} view of the keys or
+ * indices of this {@link TabularData} instance.
+ *
+ * @return a set containing the keys of this instance.
+ */
+ Set keySet();
+
+ /**
+ * Adds the specified {@link CompositeData} value to the
+ * table. The value must be non-null, of the same type
+ * as the row type of this instance, and must not have
+ * the same index as an existing value. The index is
+ * calculated using the index names of the
+ * {@link TabularType} for this instance.
+ *
+ * @param val the {@link CompositeData} value to add.
+ * @throws NullPointerException if <code>val</code> is
+ * <code>null</code>.
+ * @throws InvalidOpenTypeException if the type of the
+ * given value does not
+ * match the row type.
+ * @throws KeyAlreadyExistsException if the value has the
+ * same calculated index
+ * as an existing value.
+ */
+ void put(CompositeData val);
+
+ /**
+ * Adds each of the specified {@link CompositeData} values
+ * to the table. Each element of the array must meet the
+ * conditions given for the {@link #put(CompositeData)}
+ * method. In addition, the index of each value in the
+ * array must be distinct from the index of the other
+ * values in the array, as well as from the existing values
+ * in the table. The operation should be atomic; if one
+ * value can not be added, then none of the values should
+ * be. If the array is <code>null</code> or empty, the
+ * method simply returns.
+ *
+ * @param vals the {@link CompositeData} values to add.
+ * @throws NullPointerException if a value from the array is
+ * <code>null</code>.
+ * @throws InvalidOpenTypeException if the type of a
+ * given value does not
+ * match the row type.
+ * @throws KeyAlreadyExistsException if a value has the
+ * same calculated index
+ * as an existing value or
+ * of one of the other
+ * specified values.
+ */
+ void putAll(CompositeData[] vals);
+
+ /**
+ * Removes the {@link CompositeData} value located at the
+ * specified index. <code>null</code> is returned if the
+ * value does not exist. Otherwise, the removed value is
+ * returned.
+ *
+ * @param key the key of the value to remove.
+ * @return the removed value, or <code>null</code> if
+ * there is no value for the given key.
+ * @throws NullPointerException if the key is <code>null</code>.
+ * @throws InvalidOpenTypeException if the key does not match
+ * the {@link TabularType} of this
+ * instance.
+ */
+ CompositeData remove(Object[] key);
+
+ /**
+ * Returns the number of {@link CompositeData} values or rows
+ * in the table.
+ *
+ * @return the number of rows in the table.
+ */
+ int size();
+
+ /**
+ * Returns a textual representation of this instance. The
+ * exact format is left up to the implementation, but it
+ * should contain the name of the implementing class and
+ * the tabular type.
+ *
+ * @return a {@link java.lang.String} representation of the
+ * object.
+ */
+ String toString();
+
+ /**
+ * Returns the values associated with this instance.
+ *
+ * @return the values of this instance.
+ */
+ Collection values();
+
+}
+
diff --git a/javax/management/openmbean/TabularDataSupport.java b/javax/management/openmbean/TabularDataSupport.java
new file mode 100644
index 000000000..9dc8a0e97
--- /dev/null
+++ b/javax/management/openmbean/TabularDataSupport.java
@@ -0,0 +1,652 @@
+/* TabularDataSupport.java -- Tables of composite data structures.
+ 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 javax.management.openmbean;
+
+import java.io.Serializable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Provides an implementation of the {@link TabularData}
+ * interface using a {@link java.util.HashMap}.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class TabularDataSupport
+ implements TabularData, Serializable, Cloneable, Map
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 5720150593236309827L;
+
+ /**
+ * Mapping of rows to column values.
+ *
+ * @serial the map of rows to column values.
+ */
+ private Map dataMap;
+
+ /**
+ * The tabular type which represents this tabular data instance.
+ *
+ * @serial the type information for this instance.
+ */
+ private TabularType tabularType;
+
+ /**
+ * Constructs a new empty {@link TabularDataSupport} with the
+ * specified type. The type may not be null. This constructor
+ * simply calls the other, with the default initial capacity of
+ * <code>101</code> and default load factor of <code>0.75</code>.
+ *
+ * @param type the tabular type of this tabular data instance.
+ * @throws IllegalArgumentException if <code>type</code> is
+ * <code>null</code>.
+ */
+ public TabularDataSupport(TabularType type)
+ {
+ this(type, 101, 0.75f);
+ }
+
+ /**
+ * Constructs a new empty {@link TabularDataSupport} with the
+ * specified type and the supplied initial capacity and load factor
+ * being used for the underlying {@link java.util.HashMap}. The
+ * type may not be null and the initial capacity and load factor
+ * must be positive.
+ *
+ * @param type the tabular type of this tabular data instance.
+ * @param cap the initial capacity of the underlying map.
+ * @param lf the load factor of the underlying map.
+ * @throws IllegalArgumentException if <code>type</code> is
+ * <code>null</code>, or
+ * <code>cap</code> or
+ * <code>lf</code> are
+ * negative.
+ */
+ public TabularDataSupport(TabularType type, int cap, float lf)
+ {
+ if (type == null)
+ throw new IllegalArgumentException("The type may not be null.");
+ tabularType = type;
+ dataMap = new HashMap(cap, lf);
+ }
+
+ /**
+ * Calculates the index the specified {@link CompositeData} value
+ * would have, if it was to be added to this {@link TabularData}
+ * instance. This method includes a check that the type of the
+ * given value is the same as the row type of this instance, but not
+ * a check for existing instances of the given value. The value
+ * must also not be <code>null</code>. Possible indices are
+ * selected by the {@link TabularType#getIndexNames()} method of
+ * this instance's tabular type. The returned indices are the
+ * values of the fields in the supplied {@link CompositeData}
+ * instance that match the names given in the {@link TabularType}.
+ *
+ * @param val the {@link CompositeData} value whose index should
+ * be calculated.
+ * @return the index the value would take on, if it were to be added.
+ * @throws NullPointerException if the value is <code>null</code>.
+ * @throws InvalidOpenTypeException if the value does not match the
+ * row type of this instance.
+ */
+ public Object[] calculateIndex(CompositeData val)
+ {
+ if (!(val.getCompositeType().equals(tabularType.getRowType())))
+ throw new InvalidOpenTypeException("The type of the given value " +
+ "does not match the row type " +
+ "of this instance.");
+ List indexNames = tabularType.getIndexNames();
+ List matchingIndicies = new ArrayList(indexNames.size());
+ Iterator it = indexNames.iterator();
+ while (it.hasNext())
+ {
+ String name = (String) it.next();
+ matchingIndicies.add(val.get(name));
+ }
+ return matchingIndicies.toArray();
+ }
+
+ /**
+ * Removes all {@link CompositeData} values from the table.
+ */
+ public void clear()
+ {
+ dataMap.clear();
+ }
+
+ /**
+ * Returns a shallow clone of the information, as obtained by the
+ * {@link Object} implementation of {@link Object#clone()}. The map
+ * is also cloned, but it still references the same objects.
+ *
+ * @return a shallow clone of this {@link TabularDataSupport}.
+ */
+ public Object clone()
+ {
+ TabularDataSupport clone = null;
+ try
+ {
+ clone = (TabularDataSupport) super.clone();
+ clone.setMap((HashMap) ((HashMap) dataMap).clone());
+ }
+ catch (CloneNotSupportedException e)
+ {
+ /* This won't happen as we implement Cloneable */
+ }
+ return clone;
+ }
+
+ /**
+ * Returns true iff this instance of the {@link TabularData} class
+ * contains a {@link CompositeData} value at the specified index.
+ * The method returns <code>false</code> if the given key can
+ * not be cast to an {@link java.lang.Object} array; otherwise
+ * it returns the result of {@link #containsKey(java.lang.Object[])}.
+ *
+ *
+ * @param key the key to test for.
+ * @return true if the key maps to a {@link CompositeData} value.
+ */
+ public boolean containsKey(Object key)
+ {
+ if (key instanceof Object[])
+ return containsKey((Object[]) key);
+ else
+ return false;
+ }
+
+ /**
+ * Returns true iff this instance of the {@link TabularData} class
+ * contains a {@link CompositeData} value at the specified index.
+ * In any other circumstance, including if the given key
+ * is <code>null</code> or of the incorrect type, according to
+ * the {@link TabularType} of this instance, this method returns
+ * false.
+ *
+ * @param key the key to test for.
+ * @return true if the key maps to a {@link CompositeData} value.
+ */
+ public boolean containsKey(Object[] key)
+ {
+ if (key == null)
+ return false;
+ if (!(isKeyValid(key)))
+ return false;
+ return dataMap.containsKey(key);
+ }
+
+ /**
+ * Returns true iff this instance of the {@link TabularData} class
+ * contains the specified {@link CompositeData} value. If the given
+ * value is not an instance of {@link CompositeData}, this method
+ * simply returns false.
+ *
+ * @param val the value to test for.
+ * @return true if the value exists.
+ */
+ public boolean containsValue(Object val)
+ {
+ if (val instanceof CompositeData)
+ return containsValue((CompositeData) val);
+ else
+ return false;
+ }
+
+ /**
+ * Returns true iff this instance of the {@link TabularData} class
+ * contains the specified {@link CompositeData} value.
+ * In any other circumstance, including if the given value
+ * is <code>null</code> or of the incorrect type, according to
+ * the {@link TabularType} of this instance, this method returns
+ * false.
+ *
+ * @param val the value to test for.
+ * @return true if the value exists.
+ */
+ public boolean containsValue(CompositeData val)
+ {
+ if (val == null)
+ return false;
+ if (!(val.getCompositeType().equals(tabularType.getRowType())))
+ return false;
+ return dataMap.containsValue(val);
+ }
+
+ /**
+ * <p>
+ * Returns a set view of the mappings in this Map. Each element in the
+ * set is a Map.Entry. The set is backed by the map, so that changes in
+ * one show up in the other. Modifications made while an iterator is
+ * in progress cause undefined behavior. If the set supports removal,
+ * these methods remove the underlying mapping from the map:
+ * <code>Iterator.remove</code>, <code>Set.remove</code>,
+ * <code>removeAll</code>, <code>retainAll</code>, and <code>clear</code>.
+ * Element addition, via <code>add</code> or <code>addAll</code>, is
+ * not supported via this set.
+ * </p>
+ * <p>
+ * <strong>Note</strong>: using the
+ * {@link java.util.Map.Entry#setValue(Object) will cause corruption of
+ * the index to row mappings.
+ * </p>
+ *
+ * @return the set view of all mapping entries
+ * @see java.util.Map.Entry
+ */
+ public Set entrySet()
+ {
+ return dataMap.entrySet();
+ }
+
+ /**
+ * Compares the specified object with this object for equality.
+ * The object is judged equivalent if it is non-null, and also
+ * an instance of {@link TabularData} with the same row type,
+ * and {@link CompositeData} values. The two compared instances may
+ * be equivalent even if they represent different implementations
+ * of {@link TabularData}.
+ *
+ * @param obj the object to compare for equality.
+ * @return true if <code>obj</code> is equal to <code>this</code>.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof TabularData))
+ return false;
+ TabularData data = (TabularData) obj;
+ return tabularType.equals(data.getTabularType()) &&
+ dataMap.values().equals(data.values());
+ }
+
+ /**
+ * Retrieves the value for the specified key by simply
+ * calling <code>get((Object[]) key)</code>.
+ *
+ * @param key the key whose value should be returned.
+ * @return the matching {@link CompositeData} value, or
+ * <code>null</code> if one does not exist.
+ * @throws NullPointerException if the key is <code>null</code>.
+ * @throws ClassCastException if the key is not an instance
+ * of <code>Object[]</code>.
+ * @throws InvalidKeyException if the key does not match
+ * the {@link TabularType} of this
+ * instance.
+ */
+ public Object get(Object key)
+ {
+ return get((Object[]) key);
+ }
+
+ /**
+ * Retrieves the {@link CompositeData} value for the specified
+ * key, or <code>null</code> if no such mapping exists.
+ *
+ * @param key the key whose value should be returned.
+ * @return the matching {@link CompositeData} value, or
+ * <code>null</code> if one does not exist.
+ * @throws NullPointerException if the key is <code>null</code>.
+ * @throws InvalidKeyException if the key does not match
+ * the {@link TabularType} of this
+ * instance.
+ */
+ public CompositeData get(Object[] key)
+ {
+ if (!(isKeyValid(key)))
+ throw new InvalidKeyException("The key does not match the " +
+ "tabular type of this instance.");
+ return (CompositeData) dataMap.get(key);
+ }
+
+ /**
+ * Returns the tabular type which corresponds to this instance
+ * of {@link TabularData}.
+ *
+ * @return the tabular type for this instance.
+ */
+ public TabularType getTabularType()
+ {
+ return tabularType;
+ }
+
+ /**
+ * Returns the hash code of the composite data type. This is
+ * computed as the sum of the hash codes of each value, together
+ * with the hash code of the tabular type. These are the same
+ * elements of the type that are compared as part of the {@link
+ * #equals(java.lang.Object)} method, thus ensuring that the
+ * hashcode is compatible with the equality test.
+ *
+ * @return the hash code of this instance.
+ */
+ public int hashCode()
+ {
+ return tabularType.hashCode() + dataMap.values().hashCode();
+ }
+
+ /**
+ * Returns true if this {@link TabularData} instance
+ * contains no {@link CompositeData} values.
+ *
+ * @return true if the instance is devoid of rows.
+ */
+ public boolean isEmpty()
+ {
+ return dataMap.isEmpty();
+ }
+
+ /**
+ * Returns true if the given key is valid for the
+ * @link{TabularType} of this instance.
+ *
+ * @return true if the key is valid.
+ * @throws NullPointerException if <code>key</code>
+ * is null.
+ */
+ private boolean isKeyValid(Object[] key)
+ {
+ Iterator it = tabularType.getIndexNames().iterator();
+ CompositeType rowType = tabularType.getRowType();
+ for (int a = 0; it.hasNext(); ++a)
+ {
+ OpenType type = rowType.getType((String) it.next());
+ if (!(type.isValue(key[a])))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns a set view of the keys in this Map. The set is backed by the
+ * map, so that changes in one show up in the other. Modifications made
+ * while an iterator is in progress cause undefined behavior. If the set
+ * supports removal, these methods remove the underlying mapping from
+ * the map: <code>Iterator.remove</code>, <code>Set.remove</code>,
+ * <code>removeAll</code>, <code>retainAll</code>, and <code>clear</code>.
+ * Element addition, via <code>add</code> or <code>addAll</code>, is
+ * not supported via this set.
+ *
+ * @return the set view of all keys
+ */
+ public Set keySet()
+ {
+ return dataMap.keySet();
+ }
+
+ /**
+ * Adds the specified {@link CompositeData} value to the
+ * table. The value must be non-null, of the same type
+ * as the row type of this instance, and must not have
+ * the same index as an existing value. The index is
+ * calculated using the index names of the
+ * {@link TabularType} for this instance.
+ *
+ * @param val the {@link CompositeData} value to add.
+ * @throws NullPointerException if <code>val</code> is
+ * <code>null</code>.
+ * @throws InvalidOpenTypeException if the type of the
+ * given value does not
+ * match the row type.
+ * @throws KeyAlreadyExistsException if the value has the
+ * same calculated index
+ * as an existing value.
+ */
+ public void put(CompositeData val)
+ {
+ Object[] key = calculateIndex(val);
+ if (dataMap.containsKey(key))
+ throw new KeyAlreadyExistsException("A value with this index " +
+ "already exists.");
+ dataMap.put(key, val);
+ }
+
+ /**
+ * Adds the specified {@link CompositeData} value to the
+ * table, ignoring the supplied key, by simply calling
+ * <code>put((CompositeData) val)</code>.
+ *
+ * @param key ignored.
+ * @param val the {@link CompositeData} value to add.
+ * @return the {@link CompositeData} value.
+ * @throws NullPointerException if <code>val</code> is
+ * <code>null</code>.
+ * @throws InvalidOpenTypeException if the type of the
+ * given value does not
+ * match the row type.
+ * @throws KeyAlreadyExistsException if the value has the
+ * same calculated index
+ * as an existing value.
+ */
+ public Object put(Object key, Object val)
+ {
+ put((CompositeData) val);
+ return val;
+ }
+
+ /**
+ * Adds each of the specified {@link CompositeData} values
+ * to the table. Each element of the array must meet the
+ * conditions given for the {@link #put(CompositeData)}
+ * method. In addition, the index of each value in the
+ * array must be distinct from the index of the other
+ * values in the array, as well as from the existing values
+ * in the table. The operation should be atomic; if one
+ * value can not be added, then none of the values should
+ * be. If the array is <code>null</code> or empty, the
+ * method simply returns.
+ *
+ * @param vals the {@link CompositeData} values to add.
+ * @throws NullPointerException if a value from the array is
+ * <code>null</code>.
+ * @throws InvalidOpenTypeException if the type of a
+ * given value does not
+ * match the row type.
+ * @throws KeyAlreadyExistsException if a value has the
+ * same calculated index
+ * as an existing value or
+ * of one of the other
+ * specified values.
+ */
+ public void putAll(CompositeData[] vals)
+ {
+ if (vals == null || vals.length == 0)
+ return;
+ Map mapToAdd = new HashMap(vals.length);
+ for (int a = 0; a < vals.length; ++a)
+ {
+ Object[] key = calculateIndex(vals[a]);
+ if (dataMap.containsKey(key))
+ throw new KeyAlreadyExistsException("Element " + a + ": A " +
+ "value with this index " +
+ "already exists.");
+ mapToAdd.put(key, vals[a]);
+ }
+ dataMap.putAll(mapToAdd);
+ }
+
+ /**
+ * Converts each value from the specified map to a member of an
+ * array of {@link CompositeData} values and adds them using {@link
+ * #put(CompositeData[])}, if possible. As in {@link
+ * #put(Object,Object)}, the keys are simply ignored. This method
+ * is useful for adding the {@link CompositeData} values from a
+ * different {@link TabularData} instance, which uses the same
+ * {@link TabularType} but a different selection of index names, to
+ * this one. If the map is <code>null</code> or empty, the method
+ * simply returns.
+ *
+ * @param m the map to add. Only the values are used and must
+ * all be instances of {@link CompositeData}.
+ * @throws NullPointerException if a value from the map is
+ * <code>null</code>.
+ * @throws ClassCastException if a value from the map is not
+ * an instance of {@link CompositeData}.
+ * @throws InvalidOpenTypeException if the type of the
+ * given value does not
+ * match the row type.
+ * @throws KeyAlreadyExistsException if the value has the
+ * same calculated index
+ * as an existing value or
+ * of one of the other
+ * specified values.
+ */
+ public void putAll(Map m)
+ {
+ if (m == null || m.size() == 0)
+ return;
+ Collection vals = m.values();
+ CompositeData[] data = new CompositeData[vals.size()];
+ Iterator it = vals.iterator();
+ for (int a = 0; it.hasNext(); ++a)
+ {
+ data[a] = (CompositeData) it.next();
+ }
+ putAll(data);
+ }
+
+ /**
+ * Removes the value for the specified key by simply
+ * calling <code>remove((Object[]) key)</code>.
+ *
+ * @param key the key whose value should be removed.
+ * @return the removed value, or <code>null</code> if
+ * there is no value for the given key.
+ * @throws NullPointerException if the key is <code>null</code>.
+ * @throws ClassCastException if the key is not an instance
+ * of <code>Object[]</code>.
+ * @throws InvalidOpenTypeException if the key does not match
+ * the {@link TabularType} of this
+ * instance.
+ */
+ public Object remove(Object key)
+ {
+ return remove((Object[]) key);
+ }
+
+ /**
+ * Removes the {@link CompositeData} value located at the
+ * specified index. <code>null</code> is returned if the
+ * value does not exist. Otherwise, the removed value is
+ * returned.
+ *
+ * @param key the key of the value to remove.
+ * @return the removed value, or <code>null</code> if
+ * there is no value for the given key.
+ * @throws NullPointerException if the key is <code>null</code>.
+ * @throws InvalidOpenTypeException if the key does not match
+ * the {@link TabularType} of this
+ * instance.
+ */
+ public CompositeData remove(Object[] key)
+ {
+ if (!(isKeyValid(key)))
+ throw new InvalidKeyException("The key does not match the " +
+ "tabular type of this instance.");
+ return (CompositeData) dataMap.remove(key);
+ }
+
+ /**
+ * Package-private method to set the internal {@link java.util.Map}
+ * instance (used in cloning).
+ *
+ * @param map the new map used.
+ */
+ void setMap(Map map)
+ {
+ dataMap = map;
+ }
+
+ /**
+ * Returns the number of {@link CompositeData} values or rows
+ * in the table.
+ *
+ * @return the number of rows in the table.
+ */
+ public int size()
+ {
+ return dataMap.size();
+ }
+
+ /**
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.openmbean.TabularDataSupport</code>)
+ * and the result of calling <code>toString()</code> on the
+ * tabular type and underlying hash map instance.
+ *
+ * @return a {@link java.lang.String} representation of the
+ * object.
+ */
+ public String toString()
+ {
+ return getClass().getName()
+ + "[tabularType=" + tabularType
+ + ",dataMap=" + dataMap
+ + "]";
+ }
+
+ /**
+ * Returns a collection (or bag) view of the values in this Map. The
+ * collection is backed by the map, so that changes in one show up in
+ * the other. Modifications made while an iterator is in progress cause
+ * undefined behavior. If the collection supports removal, these methods
+ * remove the underlying mapping from the map: <code>Iterator.remove</code>,
+ * <code>Collection.remove</code>, <code>removeAll</code>,
+ * <code>retainAll</code>, and <code>clear</code>. Element addition, via
+ * <code>add</code> or <code>addAll</code>, is not supported via this
+ * collection.
+ *
+ * @return the collection view of all values
+ */
+ public Collection values()
+ {
+ return dataMap.values();
+ }
+
+}
+
diff --git a/javax/management/openmbean/TabularType.java b/javax/management/openmbean/TabularType.java
new file mode 100644
index 000000000..c38f5ea62
--- /dev/null
+++ b/javax/management/openmbean/TabularType.java
@@ -0,0 +1,269 @@
+/* TabularType.java -- Type descriptor for TabularData instances.
+ 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 javax.management.openmbean;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * The open type descriptor for instances of the
+ * {@link TabularData} class.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class TabularType
+ extends OpenType
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = 6554071860220659261L;
+
+ /**
+ * The composite type used by the rows of the table.
+ */
+ private CompositeType rowType;
+
+ /**
+ * The list of index names, which form the columns of the table.
+ * They are retained in the order given by the user, and is
+ * unmodifiable.
+ */
+ private List indexNames;
+
+ /**
+ * The hash code of this instance.
+ */
+ private transient Integer hashCode;
+
+ /**
+ * The <code>toString()</code> result of this instance.
+ */
+ private transient String string;
+
+ /**
+ * <p>
+ * Constructs a new {@link TabularType} instance for the given
+ * type name, description, row type and index names. All parameters
+ * (including the individual elements of the array of index names)
+ * must be non-null and those that are of type {@link java.lang.String}
+ * must be non-empty. The array of index names must also be non-empty.
+ * </p>
+ * <p>
+ * The result of <code>TabularData.class.getName()</code> is adopted
+ * as the class name (see {@link OpenType}). The ordering of the array
+ * elements is relevant in determining the indicies of the values in the
+ * table, and thus in the use of the
+ * {@link TabularData#get(java.lang.Object[])} and
+ * {@link TabularData#remove(java.lang.Object[])} methods of the
+ * {@link TabularData} class.
+ * </p>
+ *
+ * @param name the name of this tabular type.
+ * @param desc a description of this tabular type.
+ * @param rowType the type of the rows of the table.
+ * @param indexNames the names used to index the rows within the table.
+ * @throws IllegalArgumentException if any validity constraint listed above
+ * is broken.
+ * @throws OpenDataException if an index name does not match a corresponding
+ * name in the given row type.
+ */
+ public TabularType(String name, String desc, CompositeType rowType,
+ String[] indexNames)
+ throws OpenDataException
+ {
+ super(TabularData.class.getName(), name, desc);
+ if (rowType == null)
+ throw new IllegalArgumentException("A null row type was given.");
+ for (int a = 0; a < indexNames.length; ++a)
+ {
+ if (indexNames[a] == null)
+ throw new IllegalArgumentException("Name " + a +
+ " is null.");
+ if (indexNames[a].length() == 0)
+ throw new IllegalArgumentException("Name " + a +
+ " is the empty string.");
+ if (!(rowType.containsKey(indexNames[a])))
+ throw new OpenDataException("No matching key for " +
+ indexNames[a] + " was found in " +
+ "the supplied row type.");
+ }
+ this.rowType = rowType;
+ this.indexNames = Collections.unmodifiableList(Arrays.asList(indexNames));
+ }
+
+ /**
+ * <p>
+ * Compares this tabular data type with another object
+ * for equality. The objects are judged to be equal if:
+ * </p>
+ * <ul>
+ * <li><code>obj</code> is not null.</li>
+ * <li><code>obj</code> is an instance of
+ * {@link TabularType}.</li>
+ * <li>The type names are equal.</li>
+ * <li>The row types are equal.</li>
+ * <li>The index names are equal and in the same order.</li>
+ * </ul>
+ *
+ * @param obj the object to compare with.
+ * @return true if the conditions above hold.
+ */
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof TabularType))
+ return false;
+ TabularType ttype = (TabularType) obj;
+ return (ttype.getTypeName().equals(getTypeName())
+ && (ttype.getRowType().equals(getRowType()))
+ && (ttype.getIndexNames().equals(getIndexNames())));
+ }
+
+ /**
+ * Returns an unmodifiable list containing the index names.
+ * The ordering of these names is used to determine the indicies
+ * of the {@link CompositeData} values, and is retained from that
+ * used in the call to this object's constructor.
+ *
+ * @return an unmodifiable list of the index names used by this
+ * tabular data structure.
+ */
+ public List getIndexNames()
+ {
+ return indexNames;
+ }
+
+ /**
+ * Returns the type of the rows used by this tabular data structure.
+ *
+ * @return the row type.
+ */
+ public CompositeType getRowType()
+ {
+ return rowType;
+ }
+
+ /**
+ * <p>
+ * Returns the hash code of the tabular data type.
+ * This is computed as the sum of the hash codes of the
+ * index names together with the hash code of the type
+ * name and row type. These are the same elements
+ * of the type that are compared as part of the
+ * {@link #equals(java.lang.Object)} method, thus ensuring
+ * that the hashcode is compatible with the equality
+ * test.
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the hash code
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return the hash code of this instance.
+ */
+ public int hashCode()
+ {
+ if (hashCode == null)
+ {
+ int elementTotal = 0;
+ Iterator it = indexNames.iterator();
+ while (it.hasNext())
+ elementTotal += it.next().hashCode();
+ hashCode = Integer.valueOf(elementTotal
+ + getTypeName().hashCode()
+ + rowType.hashCode());
+ }
+ return hashCode.intValue();
+ }
+
+ /**
+ * Returns true if the specified object is a member of this
+ * tabular type. The object is judged to be so if it is
+ * an instance of {@link TabularData} with an equivalent
+ * type, according to the definition of
+ * {@link #equals(java.lang.Object)} for {@link TabularType}.
+ *
+ * @param obj the object to test for membership.
+ * @return true if the object is a member of this type.
+ */
+ public boolean isValue(Object obj)
+ {
+ if (obj instanceof TabularData)
+ {
+ TabularData data = (TabularData) obj;
+ return equals(data.getTabularType());
+ }
+ return false;
+ }
+
+ /**
+ * <p>
+ * Returns a textual representation of this instance. This
+ * is constructed using the class name
+ * (<code>javax.management.openmbean.TabularType</code>)
+ * and each element of the instance which is relevant to
+ * the definition of {@link equals(java.lang.Object)} and
+ * {@link hashCode()} (i.e. the type name, the row type
+ * and the index names).
+ * </p>
+ * <p>
+ * As instances of this class are immutable, the return value
+ * is computed just once for each instance and reused
+ * throughout its life.
+ * </p>
+ *
+ * @return a @link{java.lang.String} instance representing
+ * the instance in textual form.
+ */
+ public String toString()
+ {
+ if (string == null)
+ string = getClass().getName()
+ + "[name=" + getTypeName()
+ + ", rowType=" + rowType
+ + ", indexNames=" + indexNames
+ + "]";
+ return string;
+ }
+
+}
diff --git a/javax/management/openmbean/package.html b/javax/management/openmbean/package.html
new file mode 100644
index 000000000..d915007d4
--- /dev/null
+++ b/javax/management/openmbean/package.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.lang.management package.
+ 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. -->
+
+<html>
+<head><title>GNU Classpath - javax.management.openmbean</title></head>
+
+<body>
+
+<p>
+Provides the data types and descriptor classes for the
+<emph>Open MBean</emph>s. Open MBeans are provided in
+order to aid interoperability with non-Java management
+systems. Unlike normal MBeans, which make use of any
+Java data type, Open MBeans use a restricted set of types
+which can then be mapped over remote connections, including
+to non-Java systems.
+</p>
+<p>
+Normal MBeans are described using an instance of
+{@link javax.management.MBeanInfo} with appropriate representations
+of the attributes, constructors and operators associated with
+the bean. Open MBeans are described in the same way, but by
+using subtypes of these entities, which type the bean data using
+instances of {@link javax.management.openmbean.OpenType}. Open
+types differ from Java types, and are explicitly specified in order
+to obtain interoperability with other systems.
+</p>
+</body>
+</html>
diff --git a/javax/naming/Name.java b/javax/naming/Name.java
index f0475766a..24a425403 100644
--- a/javax/naming/Name.java
+++ b/javax/naming/Name.java
@@ -62,6 +62,8 @@ import java.util.Enumeration;
*/
public interface Name extends Cloneable, Serializable, Comparable
{
+ // This class is implemented as gnu.javax.naming.ictxImpl.trans.GnuName
+
long serialVersionUID = -3617482732056931635L;
/**
@@ -94,22 +96,27 @@ public interface Name extends Cloneable, Serializable, Comparable
* Returns the components till the given index as a <code>Name</code>.
* The returned <code>Name</code> can be modified without changing the
* original.
+ *
+ * @param posn the ending position, exclusive
*
* @exception ArrayIndexOutOfBoundsException if the given index is smaller
* then zero or greater then or equal to <code>size()</code>.
*/
- Name getPrefix(int i);
+ Name getPrefix(int posn);
/**
* Returns the components from the given index till the end as a
* <code>Name</code>.
* The returned <code>Name</code> can be modified without changing the
* original.
+ *
+ * @param posn the starting position, inclusive. If it is equal to the size
+ * of the name, the empty name is returned.
*
* @exception ArrayIndexOutOfBoundsException if the given index is smaller
* then zero or greater then or equal to <code>size()</code>.
*/
- Name getSuffix(int i);
+ Name getSuffix(int posn);
/**
* Adds the given <code>String</code> component to the end of this
@@ -145,7 +152,8 @@ public interface Name extends Cloneable, Serializable, Comparable
/**
* Inserts all the components of the given <code>Name</code> to this
- * <code>Name</code> at the given index. The method modifies the current
+ * <code>Name</code> at the given index. Components after this index
+ * (if any) are shifted up. The method modifies the current
* <code>Name</code> and then returns it.
*
* @exception ArrayIndexOutOfBoundsException if the given index is smaller
diff --git a/javax/naming/spi/NamingManager.java b/javax/naming/spi/NamingManager.java
index a36d519d7..67c8e3510 100644
--- a/javax/naming/spi/NamingManager.java
+++ b/javax/naming/spi/NamingManager.java
@@ -190,9 +190,12 @@ public class NamingManager
String scheme, Hashtable environment)
throws NamingException
{
- // Specified as the default in the docs. Unclear if this is
- // right for us.
- String defaultPrefix = "com.sun.jndi.url";
+ // Doc specifies com.sun.jndi.url as the final destination, but we cannot
+ // put our classes into such namespace.
+ String defaultPrefix = "gnu.javax.naming.jndi.url";
+
+ // The final default location, as specified in the documentation.
+ String finalPrefix = "com.sun.jndi.url";
StringBuffer allPrefixes = new StringBuffer();
@@ -215,6 +218,8 @@ public class NamingManager
if (allPrefixes.length() > 0)
allPrefixes.append(':');
allPrefixes.append(defaultPrefix);
+ allPrefixes.append(':');
+ allPrefixes.append(finalPrefix);
scheme = scheme + "." + scheme + "URLContextFactory";
@@ -228,12 +233,21 @@ public class NamingManager
Class factoryClass = forName(tryClass);
if (factoryClass != null)
{
- ObjectFactory factory = (ObjectFactory) factoryClass.newInstance();
- Object obj = factory.getObjectInstance(refInfo, name, nameCtx,
- environment);
- Context ctx = (Context) obj;
- if (ctx != null)
- return ctx;
+ Object obj;
+ try
+ {
+ ObjectFactory factory = (ObjectFactory) factoryClass.newInstance();
+ obj = factory.getObjectInstance(refInfo, name, nameCtx,
+ environment);
+ Context ctx = (Context) obj;
+ if (ctx != null)
+ return ctx;
+ }
+ catch (RuntimeException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
}
}
catch (ClassNotFoundException _1)
diff --git a/javax/net/ssl/KeyManagerFactory.java b/javax/net/ssl/KeyManagerFactory.java
index ab8abd626..33f2fda9c 100644
--- a/javax/net/ssl/KeyManagerFactory.java
+++ b/javax/net/ssl/KeyManagerFactory.java
@@ -132,49 +132,55 @@ public class KeyManagerFactory
}
/**
- * Get an instance of the named key manager factory, from the first
+ * Create an instance of the named key manager factory, from the first
* provider that implements it.
- *
+ *
* @param algorithm The type of key manager factory to get.
* @return An appropriate implementation of that algoritm.
- * @throws NoSuchAlgorithmException If no provider implements the
- * requested algorithm.
+ * @throws NoSuchAlgorithmException If no provider implements the requested
+ * algorithm.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static final KeyManagerFactory getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- Provider[] provs = Security.getProviders();
- for (int i = 0; i < provs.length; i++)
- {
- try
- {
- return getInstance(algorithm, provs[i]);
- }
- catch (NoSuchAlgorithmException ignore)
- {
- }
- }
+ Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
+ for (int i = 0; i < p.length; i++)
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
/**
- * Get an instance of the named key manager factory, from the named
+ * Create an instance of the named key manager factory, from the named
* provider.
- *
+ *
* @param algorithm The type of key manager factory to get.
- * @param provider The name of the provider to get the
- * implementation from.
+ * @param provider The name of the provider to get the implementation from.
* @return An appropriate implementation of that algorithm.
- * @throws NoSuchAlgorithmException If the provider does not
- * implement the requested algorithm.
- * @throws NoSuchProviderException If the named provider does not
- * exist.
+ * @throws NoSuchAlgorithmException If the provider does not implement the
+ * requested algorithm.
+ * @throws NoSuchProviderException If the named provider does not exist.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
- public static final KeyManagerFactory getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ public static final KeyManagerFactory getInstance(String algorithm,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
if (provider == null)
- throw new IllegalArgumentException("provider is null");
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
@@ -182,40 +188,48 @@ public class KeyManagerFactory
}
/**
- * Get an instance of the named key manager factory, from the given
+ * Create an instance of the named key manager factory, from the given
* provider.
- *
+ *
* @param algorithm The type of key manager factory to get.
* @param provider The provider to get the implementation from.
* @return An appropriate implementation of that algorithm.
- * @throws NoSuchAlgorithmException If the provider does not
- * implement the requested algorithm.
- * @throws IllegalArgumentException If <i>provider</i> is null.
+ * @throws NoSuchAlgorithmException If the provider does not implement the
+ * requested algorithm.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
- public static final KeyManagerFactory getInstance(String algorithm, Provider provider)
- throws NoSuchAlgorithmException
+ public static final KeyManagerFactory getInstance(String algorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("provider is null");
+ StringBuilder sb = new StringBuilder("KeyManagerFactory algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new KeyManagerFactory((KeyManagerFactorySpi)
- Engine.getInstance(KEY_MANAGER_FACTORY, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(KEY_MANAGER_FACTORY, algorithm, provider);
+ return new KeyManagerFactory((KeyManagerFactorySpi) spi, provider, algorithm);
}
- catch (InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // -------------------------------------------------------------------
-
/**
* Returns the name of this key manager factory algorithm.
*
diff --git a/javax/net/ssl/SSLContext.java b/javax/net/ssl/SSLContext.java
index eaf3e3638..64bb09ade 100644
--- a/javax/net/ssl/SSLContext.java
+++ b/javax/net/ssl/SSLContext.java
@@ -91,102 +91,103 @@ public class SSLContext
this.protocol = protocol;
}
- // Class methods.
- // ------------------------------------------------------------------
-
/**
- * Get an instance of a context for the specified protocol from the
- * first provider that implements it.
- *
+ * Get an instance of a context for the specified protocol from the first
+ * provider that implements it.
+ *
* @param protocol The name of the protocol to get a context for.
* @return The new context.
- * @throws NoSuchAlgorithm If no provider implements the given
- * protocol.
+ * @throws NoSuchAlgorithmException If no provider implements the given
+ * protocol.
+ * @throws IllegalArgumentException if <code>protocol</code> is
+ * <code>null</code> or is an empty string.
*/
public static final SSLContext getInstance(String protocol)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- Provider[] provs = Security.getProviders();
- for (int i = 0; i < provs.length; i++)
- {
- try
- {
- return getInstance(protocol, provs[i]);
- }
- catch (NoSuchAlgorithmException ignore)
- {
- }
- }
+ Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
+ for (int i = 0; i < p.length; i++)
+ try
+ {
+ return getInstance(protocol, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(protocol);
}
/**
- * Get an instance of a context for the specified protocol from the
- * named provider.
- *
+ * Get an instance of a context for the specified protocol from the named
+ * provider.
+ *
* @param protocol The name of the protocol to get a context for.
- * @param provider The name of the provider to get the
- * implementation from.
+ * @param provider The name of the provider to get the implementation from.
* @return The new context.
- * @throws NoSuchAlgorithmException If the provider does not
- * implement the given protocol.
- * @throws NoSuchProviderException If the named provider does not
- * exist.
- * @throws IllegalArgumentException If <i>provider</i> is null.
+ * @throws NoSuchAlgorithmException If the provider does not implement the
+ * given protocol.
+ * @throws NoSuchProviderException If the named provider does not exist.
+ * @throws IllegalArgumentException if either <code>protocol</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>protocol</code> is an empty string.
*/
- public static final SSLContext getInstance(String protocol,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ public static final SSLContext getInstance(String protocol, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
if (provider == null)
- {
- throw new IllegalArgumentException("null provider");
- }
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
- {
- throw new NoSuchProviderException(provider);
- }
+ throw new NoSuchProviderException(provider);
return getInstance(protocol, p);
}
/**
- * Get an instance of a context for the specified protocol from the
- * specified provider.
- *
+ * Get an instance of a context for the specified protocol from the specified
+ * provider.
+ *
* @param protocol The name of the protocol to get a context for.
- * @param provider The name of the provider to get the
- * implementation from.
+ * @param provider The name of the provider to get the implementation from.
* @return The new context.
- * @throws NoSuchAlgorithmException If the provider does not
- * implement the given protocol.
- * @throws IllegalArgumentException If <i>provider</i> is null.
+ * @throws NoSuchAlgorithmException If the provider does not implement the
+ * given protocol.
+ * @throws IllegalArgumentException if either <code>protocol</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>protocol</code> is an empty string.
*/
- public static final SSLContext getInstance(String protocol,
- Provider provider)
- throws NoSuchAlgorithmException
+ public static final SSLContext getInstance(String protocol, Provider provider)
+ throws NoSuchAlgorithmException
{
+ StringBuilder sb = new StringBuilder("SSLContext for protocol [")
+ .append(protocol).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new SSLContext((SSLContextSpi)
- Engine.getInstance(SSL_CONTEXT, protocol, provider),
- provider, protocol);
+ Object spi = Engine.getInstance(SSL_CONTEXT, protocol, provider);
+ return new SSLContext((SSLContextSpi) spi, provider, protocol);
}
- catch (InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- NoSuchAlgorithmException nsae = new NoSuchAlgorithmException(protocol);
- throw (NoSuchAlgorithmException) nsae.initCause(ite);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- NoSuchAlgorithmException nsae = new NoSuchAlgorithmException(protocol);
- throw (NoSuchAlgorithmException) nsae.initCause(cce);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // -----------------------------------------------------------------
-
/**
* Returns the set of SSL contexts available for client connections.
*
diff --git a/javax/net/ssl/TrustManagerFactory.java b/javax/net/ssl/TrustManagerFactory.java
index 62ab1c2df..f868ae75b 100644
--- a/javax/net/ssl/TrustManagerFactory.java
+++ b/javax/net/ssl/TrustManagerFactory.java
@@ -93,96 +93,105 @@ public class TrustManagerFactory
this.algorithm = algorithm;
}
- // Class methods.
- // -------------------------------------------------------------------------
-
/**
- * Returns an instance of a trust manager factory for the given algorithm
- * from the first provider that implements it.
- *
+ * Returns an instance of a trust manager factory for the given algorithm from
+ * the first provider that implements it.
+ *
* @param algorithm The name of the algorithm to get.
* @return The instance of the trust manager factory.
* @throws NoSuchAlgorithmException If no provider implements the given
- * algorithm.
+ * algorithm.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static final TrustManagerFactory getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- Provider[] provs = Security.getProviders();
- for (int i = 0; i < provs.length; i++)
- {
- try
- {
- return getInstance(algorithm, provs[i]);
- }
- catch (NoSuchAlgorithmException ignore)
- {
- }
- }
+ Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
+ for (int i = 0; i < p.length; i++)
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
/**
- * Returns an instance of a trust manager factory for the given algorithm
- * from the named provider.
- *
+ * Returns an instance of a trust manager factory for the given algorithm from
+ * the named provider.
+ *
* @param algorithm The name of the algorithm to get.
* @param provider The name of the provider to get the instance from.
* @return The instance of the trust manager factory.
* @throws NoSuchAlgorithmException If the provider does not implement the
- * given algorithm.
+ * given algorithm.
* @throws NoSuchProviderException If there is no such named provider.
- * @throws IllegalArgumentException If the provider argument is null.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static final TrustManagerFactory getInstance(String algorithm,
String provider)
throws NoSuchAlgorithmException, NoSuchProviderException
{
if (provider == null)
- {
- throw new IllegalArgumentException();
- }
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
- {
- throw new NoSuchProviderException(provider);
- }
+ throw new NoSuchProviderException(provider);
return getInstance(algorithm, p);
}
/**
- * Returns an instance of a trust manager factory for the given algorithm
- * from the specified provider.
- *
+ * Returns an instance of a trust manager factory for the given algorithm from
+ * the specified provider.
+ *
* @param algorithm The name of the algorithm to get.
* @param provider The provider to get the instance from.
* @return The instance of the trust manager factory.
* @throws NoSuchAlgorithmException If the provider does not implement the
- * given algorithm.
- * @throws IllegalArgumentException If the provider argument is null.
+ * given algorithm.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static final TrustManagerFactory getInstance(String algorithm,
Provider provider)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- if (provider == null)
- {
- throw new IllegalArgumentException();
- }
+ StringBuilder sb = new StringBuilder("TrustManagerFactory algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new TrustManagerFactory((TrustManagerFactorySpi)
- Engine.getInstance(TRUST_MANAGER_FACTORY, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(TRUST_MANAGER_FACTORY, algorithm, provider);
+ return new TrustManagerFactory((TrustManagerFactorySpi) spi,
+ provider,
+ algorithm);
}
- catch (InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
/**
diff --git a/javax/rmi/ssl/SslRMIClientSocketFactory.java b/javax/rmi/ssl/SslRMIClientSocketFactory.java
new file mode 100644
index 000000000..1fed5824c
--- /dev/null
+++ b/javax/rmi/ssl/SslRMIClientSocketFactory.java
@@ -0,0 +1,166 @@
+/* SslRMIClientSocketFactory.java --
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.rmi.ssl;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+import java.util.StringTokenizer;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.SSLSocket;
+import java.net.Socket;
+import java.rmi.server.RMIClientSocketFactory;
+
+/**
+ * SslRMIClientSocketFactory
+ *
+ * This class implements an RMIClientSocketFactory for SSL sockets.
+ * it uses the defeult SSLClientSocketFactory.
+ *
+ * This class can optionally use the following system properties, if set:
+ * <code>javax.rmi.ssl.client.enabledCipherSuites</code>
+ * <code>javax.rmi.ssl.client.enabledProtocols</code>
+ *
+ * These properties will specify a list of SSL/TLS cipher suites and protocols,
+ * respectively, to enable on the created sockets.
+ *
+ * Both properties should consist of a comma-separated list.
+ *
+ * @author Sven de Marothy
+ * @since 1.5
+ */
+public class SslRMIClientSocketFactory
+ implements RMIClientSocketFactory, Serializable
+{
+
+ /**
+ * Compatible with JDK 1.5
+ */
+ private static final long serialVersionUID = -8310631444933958385L;
+
+ private String[] enabledCipherSuites, enabledProtocols;
+
+ /**
+ * The SSL Socket factory.
+ */
+ private static SSLSocketFactory socketFactory =
+ (SSLSocketFactory)SSLSocketFactory.getDefault();
+
+ /**
+ * Creates a new SslRMIClientSocketFactory
+ */
+ public SslRMIClientSocketFactory()
+ {
+ enabledCipherSuites = getProp("javax.rmi.ssl.client.enabledCipherSuites");
+ enabledProtocols = getProp("javax.rmi.ssl.client.enabledProtocols");
+ }
+
+ private String[] getProp(String p)
+ {
+ StringTokenizer st;
+ try
+ {
+ String o = (String)System.getProperty( p );
+ st = new StringTokenizer( o, "," );
+ }
+ catch(SecurityException se)
+ {
+ return null;
+ }
+
+ int n = st.countTokens();
+ if( n < 1 )
+ return null;
+ String[] strs = new String[ n ];
+ for( int i = 0; i < n; i++ )
+ strs[i] = st.nextToken().trim();
+
+ return strs;
+ }
+
+ /**
+ * Creates an SSLSocket on a given port
+ *
+ * @throws IOException if an error occurs on socket creation.
+ */
+ public Socket createSocket(String host, int port) throws IOException
+ {
+ SSLSocket socket = (SSLSocket)socketFactory.
+ createSocket( host, port );
+ if( enabledCipherSuites != null )
+ socket.setEnabledCipherSuites( enabledCipherSuites );
+ if( enabledProtocols != null )
+ socket.setEnabledProtocols( enabledProtocols );
+ return socket;
+ }
+
+ /**
+ * Compare two SslRMIServerSocketFactor instances
+ */
+ public boolean equals(Object obj)
+ {
+ if( !(obj instanceof SslRMIClientSocketFactory) )
+ return false;
+ SslRMIClientSocketFactory s = (SslRMIClientSocketFactory)obj;
+
+ if(!SslRMIServerSocketFactory.
+ cmpStrArray(enabledCipherSuites, s.enabledCipherSuites))
+ return false;
+
+ if(!SslRMIServerSocketFactory.
+ cmpStrArray(enabledProtocols, s.enabledProtocols))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Returns the hash code of this object.
+ */
+ public int hashCode()
+ {
+ int hash = 0;
+ if( enabledCipherSuites != null )
+ for(int i = 0; i < enabledCipherSuites.length; i++ )
+ hash = hash ^ enabledCipherSuites[i].hashCode();
+ if( enabledProtocols != null )
+ for(int i = 0; i < enabledProtocols.length; i++ )
+ hash = hash ^ enabledProtocols[i].hashCode();
+ return hash;
+ }
+}
diff --git a/javax/rmi/ssl/SslRMIServerSocketFactory.java b/javax/rmi/ssl/SslRMIServerSocketFactory.java
new file mode 100644
index 000000000..56f6de11c
--- /dev/null
+++ b/javax/rmi/ssl/SslRMIServerSocketFactory.java
@@ -0,0 +1,213 @@
+/* SslRMIServerSocketFactory.java --
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.rmi.ssl;
+
+import java.io.IOException;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLServerSocket;
+import java.net.ServerSocket;
+import java.rmi.server.RMIServerSocketFactory;
+
+/**
+ * SslRMIServerSocketFactory
+ *
+ * This class implements an RMIServerSocketFactory for SSL sockets.
+ * it uses the defeult SSLServerSocketFactory.
+ *
+ * @author Sven de Marothy
+ * @since 1.5
+ */
+public class SslRMIServerSocketFactory implements RMIServerSocketFactory
+{
+ private String[] enabledCipherSuites, enabledProtocols;
+ private boolean needClientAuth;
+
+ /**
+ * The SSL ServerSocket factory.
+ */
+ private static SSLServerSocketFactory socketFactory =
+ (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
+
+ /**
+ * Creates a new SslRMIServerSocketFactory with the default socket
+ * cipher suites and protocols, and without requiring client authorisation.
+ */
+ public SslRMIServerSocketFactory()
+ {
+ enabledCipherSuites = enabledProtocols = null;
+ needClientAuth = false;
+ }
+
+ /**
+ * Creates a new SslRMIServerSocketFactory with a given set of socket
+ * cipher suites and protocols. needClientAuth specifies if client
+ * authorization is required.
+ *
+ * @param enabledCipherSuites - the cypher suites to enable
+ * or <code>null</code> for the defauls.
+ * @param enabledCipherSuites - the protocols to enable,
+ * or <code>null</code> for the defauls.
+ * @param needClientAuth - specify client authorization requirement.
+ * @throws IllegalArgumentException if any of the ciphers or protocols
+ * specified are not available.
+ */
+ public SslRMIServerSocketFactory(String[] enabledCipherSuites,
+ String[] enabledProtocols,
+ boolean needClientAuth)
+ {
+ this.enabledCipherSuites = enabledCipherSuites;
+ this.enabledProtocols = enabledProtocols;
+ this.needClientAuth = needClientAuth;
+ try
+ {
+ if( enabledProtocols != null || enabledCipherSuites != null )
+ createServerSocket( 0 ); // stupid way to test the parameters
+ }
+ catch(IOException e)
+ {
+ // Can this happen? FIXME.
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Creates an SSLServerSocket on a given port
+ *
+ * @throws IOException if an error occurs on socket creation.
+ */
+ public ServerSocket createServerSocket(int port) throws IOException
+ {
+ SSLServerSocket socket = (SSLServerSocket)socketFactory.
+ createServerSocket( port );
+ if( enabledCipherSuites != null )
+ socket.setEnabledCipherSuites( enabledCipherSuites );
+ if( enabledProtocols != null )
+ socket.setEnabledProtocols( enabledProtocols );
+ socket.setNeedClientAuth( needClientAuth );
+ return socket;
+ }
+
+ /**
+ * Compare two SslRMIServerSocketFactor instances
+ */
+ public boolean equals(Object obj)
+ {
+ if( !(obj instanceof SslRMIServerSocketFactory) )
+ return false;
+ SslRMIServerSocketFactory s = (SslRMIServerSocketFactory)obj;
+ if( needClientAuth != s.needClientAuth )
+ return false;
+
+ if(!cmpStrArray(enabledCipherSuites, s.enabledCipherSuites))
+ return false;
+
+ if(!cmpStrArray(enabledProtocols, s.enabledProtocols))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Compare two string arrays.
+ */
+ static boolean cmpStrArray(String[] a, String[] b)
+ {
+ if( ( a == null || b == null ) && a != b )
+ return false;
+
+ if( a != null )
+ {
+ if( a.length != b.length )
+ return false;
+ for( int i = 0; i < a.length; i++ )
+ if(!a[i].equals(b[i]))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the enabled cipher suites, or <code>null</code>
+ * if the defaults are to be used.
+ * @returns a string array of cipher suite names
+ */
+ public String[] getEnabledCipherSuites()
+ {
+ if( enabledCipherSuites == null )
+ return null;
+ return (String[])enabledCipherSuites.clone();
+ }
+
+ /**
+ * Returns the enabled protocols, or <code>null</code> if the defaults are
+ * to be used.
+ *
+ * @returns a string array of protocol names
+ */
+ public String[] getEnabledProtocols()
+ {
+ if( enabledProtocols == null )
+ return null;
+ return (String[])enabledProtocols.clone();
+ }
+
+ /**
+ * Returns whether client authorization is needed.
+ */
+ public boolean getNeedClientAuth()
+ {
+ return needClientAuth;
+ }
+
+ /**
+ * Returns the hash code of this object.
+ */
+ public int hashCode()
+ {
+ int hash = 0;
+ if( enabledCipherSuites != null )
+ for(int i = 0; i < enabledCipherSuites.length; i++ )
+ hash = hash ^ enabledCipherSuites[i].hashCode();
+ if( enabledProtocols != null )
+ for(int i = 0; i < enabledProtocols.length; i++ )
+ hash = hash ^ enabledProtocols[i].hashCode();
+ hash = ( needClientAuth ) ? (hash^0xFFFF) : hash;
+ return hash;
+ }
+} \ No newline at end of file
diff --git a/javax/security/auth/login/LoginContext.java b/javax/security/auth/login/LoginContext.java
index 740e67b8b..17641e65b 100644
--- a/javax/security/auth/login/LoginContext.java
+++ b/javax/security/auth/login/LoginContext.java
@@ -1,5 +1,5 @@
/* LoginContext.java
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -91,6 +91,9 @@ public class LoginContext
Configuration config)
throws LoginException
{
+ this.name = name;
+ this.subject = subject;
+ this.cbHandler = cbHandler;
if (config == null)
config = Configuration.getConfig();
AppConfigurationEntry[] entries = config.getAppConfigurationEntry (name);
@@ -104,9 +107,6 @@ public class LoginContext
sharedState = new HashMap();
for (int i = 0; i < entries.length; i++)
modules[i] = lookupModule (entries[i], subject, sharedState);
- this.name = name;
- this.subject = subject;
- this.cbHandler = cbHandler;
}
/**
diff --git a/javax/swing/AbstractButton.java b/javax/swing/AbstractButton.java
index a9ec0c037..63f827a1a 100644
--- a/javax/swing/AbstractButton.java
+++ b/javax/swing/AbstractButton.java
@@ -199,7 +199,7 @@ public abstract class AbstractButton extends JComponent
Icon pressed_icon;
/** The icon displayed when the button is disabled. */
- Icon disabeldIcon;
+ Icon disabledIcon;
/** The icon displayed when the button is selected. */
Icon selectedIcon;
@@ -1364,6 +1364,9 @@ public abstract class AbstractButton extends JComponent
{
if (horizontalTextPosition == t)
return;
+ if (t != LEFT && t != CENTER && t != RIGHT && t != LEADING
+ && t != TRAILING)
+ throw new IllegalArgumentException("Invalid alignment.");
int old = horizontalTextPosition;
horizontalTextPosition = t;
@@ -1442,6 +1445,8 @@ public abstract class AbstractButton extends JComponent
{
if (verticalTextPosition == t)
return;
+ if (t != TOP && t != CENTER && t != BOTTOM)
+ throw new IllegalArgumentException("Invalid alignment.");
int old = verticalTextPosition;
verticalTextPosition = t;
@@ -1720,14 +1725,14 @@ public abstract class AbstractButton extends JComponent
*/
public Icon getDisabledIcon()
{
- if (disabeldIcon == null && default_icon instanceof ImageIcon)
+ if (disabledIcon == null && default_icon instanceof ImageIcon)
{
Image iconImage = ((ImageIcon) default_icon).getImage();
Image grayImage = GrayFilter.createDisabledImage(iconImage);
- disabeldIcon = new ImageIcon(grayImage);
+ disabledIcon = new ImageIcon(grayImage);
}
- return disabeldIcon;
+ return disabledIcon;
}
/**
@@ -1741,7 +1746,11 @@ public abstract class AbstractButton extends JComponent
*/
public void setDisabledIcon(Icon d)
{
- disabeldIcon = d;
+ if (disabledIcon == d)
+ return;
+ Icon old = disabledIcon;
+ disabledIcon = d;
+ firePropertyChange(DISABLED_ICON_CHANGED_PROPERTY, old, d);
revalidate();
repaint();
}
diff --git a/javax/swing/ButtonGroup.java b/javax/swing/ButtonGroup.java
index 2f8d19831..efa36b5f6 100644
--- a/javax/swing/ButtonGroup.java
+++ b/javax/swing/ButtonGroup.java
@@ -1,5 +1,5 @@
/* ButtonGroup.java --
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -65,10 +65,9 @@ import java.util.Vector;
*/
public class ButtonGroup implements Serializable
{
- /** DOCUMENT ME! */
private static final long serialVersionUID = 4259076101881721375L;
- /** The buttons added to this button group. */
+ /** Stores references to the buttons added to this button group. */
protected Vector buttons = new Vector();
/** The currently selected button model. */
@@ -83,12 +82,20 @@ public class ButtonGroup implements Serializable
}
/**
- * Adds a button to this group.
+ * Adds a button to this group. If the button is in the selected state, then:
+ * <ul>
+ * <li>if the group has no current selection, the new button becomes the
+ * selected button for the group;</li>
+ * <li>if the group already has a selected button, the new button is set to
+ * "not selected".</li>
+ * </ul>
*
- * @param b the button to add
+ * @param b the button to add (<code>null</code> is ignored).
*/
public void add(AbstractButton b)
{
+ if (b == null)
+ return;
b.getModel().setGroup(this);
if (b.isSelected())
{
@@ -96,17 +103,24 @@ public class ButtonGroup implements Serializable
sel = b.getModel();
else
b.setSelected(false);
- } buttons.addElement(b);
+ }
+ buttons.addElement(b);
}
/**
- * Removed a given button from this group.
+ * Removes the specified button from this group. If the button is the
+ * selected button, the current selection is set to <code>null</code>.
+ * The group for the removed button's model is set to <code>null</code>.
*
- * @param b the button to remove
+ * @param b the button to remove (<code>null</code> is ignored).
*/
public void remove(AbstractButton b)
{
+ if (b == null)
+ return;
b.getModel().setGroup(null);
+ if (b.getModel() == sel)
+ sel = null;
buttons.removeElement(b);
}
@@ -132,19 +146,20 @@ public class ButtonGroup implements Serializable
}
/**
- * DOCUMENT ME!
+ * Returns the button that has the specified model, or <code>null</code> if
+ * there is no such button in the group.
*
- * @param m DOCUMENT ME!
+ * @param m the button model.
*
- * @return DOCUMENT ME!
+ * @return The button that has the specified model, or <code>null</code>.
*/
- AbstractButton FindButton(ButtonModel m)
+ AbstractButton findButton(ButtonModel m)
{
for (int i = 0; i < buttons.size(); i++)
{
- AbstractButton a = (AbstractButton) buttons.get(i);
- if (a.getModel() == m)
- return a;
+ AbstractButton a = (AbstractButton) buttons.get(i);
+ if (a.getModel() == m)
+ return a;
}
return null;
}
@@ -168,7 +183,7 @@ public class ButtonGroup implements Serializable
if (old != null)
old.setSelected(false);
- AbstractButton button = FindButton(old);
+ AbstractButton button = findButton(old);
if (button != null)
button.repaint();
}
@@ -180,10 +195,10 @@ public class ButtonGroup implements Serializable
* Checks if the given <code>ButtonModel</code> is selected in this button
* group.
*
- * @param m DOCUMENT ME!
+ * @param m the button model (<code>null</code> permitted).
*
- * @return true of given <code>ButtonModel</code> is selected, false
- * otherwise
+ * @return <code>true</code> if <code>m</code> is the selected button model
+ * in this group, and <code>false</code> otherwise.
*/
public boolean isSelected(ButtonModel m)
{
diff --git a/javax/swing/DefaultBoundedRangeModel.java b/javax/swing/DefaultBoundedRangeModel.java
index 10de4b948..efca148f4 100644
--- a/javax/swing/DefaultBoundedRangeModel.java
+++ b/javax/swing/DefaultBoundedRangeModel.java
@@ -1,6 +1,6 @@
/* DefaultBoundedRangeModel.java -- Default implementation
of BoundedRangeModel.
- Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,6 +39,9 @@ exception statement from your version. */
package javax.swing;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.EventListener;
@@ -440,4 +443,33 @@ public class DefaultBoundedRangeModel
{
return (ChangeListener[]) getListeners(ChangeListener.class);
}
+
+ /**
+ * Provides serialization support.
+ *
+ * @param stream the output stream (<code>null</code> not permitted).
+ *
+ * @throws IOException if there is an I/O error.
+ */
+ private void writeObject(ObjectOutputStream stream)
+ throws IOException
+ {
+ stream.defaultWriteObject();
+ }
+
+ /**
+ * Provides serialization support.
+ *
+ * @param stream the input stream (<code>null</code> not permitted).
+ *
+ * @throws IOException if there is an I/O error.
+ * @throws ClassNotFoundException if there is a classpath problem.
+ */
+ private void readObject(ObjectInputStream stream)
+ throws ClassNotFoundException, IOException
+ {
+ stream.defaultReadObject();
+ listenerList = new EventListenerList();
+ }
+
}
diff --git a/javax/swing/JComboBox.java b/javax/swing/JComboBox.java
index efb04592b..c75a94bdc 100644
--- a/javax/swing/JComboBox.java
+++ b/javax/swing/JComboBox.java
@@ -471,6 +471,7 @@ public class JComboBox extends JComponent implements ItemSelectable,
public void setSelectedItem(Object item)
{
dataModel.setSelectedItem(item);
+ fireActionEvent();
}
/**
@@ -1028,7 +1029,8 @@ public class JComboBox extends JComponent implements ItemSelectable,
}
/**
- * This method hides combo box's popup whenever TAB key is pressed.
+ * This method is fired whenever a key is pressed with the combo box
+ * in focus
*
* @param e The KeyEvent indicating which key was pressed.
*/
@@ -1036,15 +1038,6 @@ public class JComboBox extends JComponent implements ItemSelectable,
{
if (e.getKeyCode() == KeyEvent.VK_TAB)
setPopupVisible(false);
- else if (keySelectionManager != null)
- {
- int i = keySelectionManager.selectionForKey(e.getKeyChar(),
- getModel());
- if (i >= 0)
- setSelectedIndex(i);
- else
- super.processKeyEvent(e);
- }
else
super.processKeyEvent(e);
}
@@ -1066,7 +1059,7 @@ public class JComboBox extends JComponent implements ItemSelectable,
*/
public KeySelectionManager getKeySelectionManager()
{
- return null;
+ return keySelectionManager;
}
/**
@@ -1098,7 +1091,7 @@ public class JComboBox extends JComponent implements ItemSelectable,
*/
protected KeySelectionManager createDefaultKeySelectionManager()
{
- return null;
+ return new DefaultKeySelectionManager();
}
/**
@@ -1471,4 +1464,34 @@ public class JComboBox extends JComponent implements ItemSelectable,
// Nothing to do here.
}
}
+
+ private class DefaultKeySelectionManager
+ implements KeySelectionManager
+ {
+
+ public int selectionForKey(char aKey, ComboBoxModel aModel)
+ {
+ int selectedIndex = getSelectedIndex();
+
+ // Start at currently selected item and iterate to end of list
+ for (int i = selectedIndex + 1; i < aModel.getSize(); i++)
+ {
+ String nextItem = aModel.getElementAt(i).toString();
+
+ if (nextItem.charAt(0) == aKey)
+ return i;
+ }
+
+ // Wrap to start of list if no match yet
+ for (int i = 0; i <= selectedIndex; i++)
+ {
+ String nextItem = aModel.getElementAt(i).toString();
+
+ if (nextItem.charAt(0) == aKey)
+ return i;
+ }
+
+ return - 1;
+ }
+ }
}
diff --git a/javax/swing/JComponent.java b/javax/swing/JComponent.java
index e9856d12b..fa8350294 100644
--- a/javax/swing/JComponent.java
+++ b/javax/swing/JComponent.java
@@ -48,12 +48,10 @@ import java.awt.EventQueue;
import java.awt.FocusTraversalPolicy;
import java.awt.Font;
import java.awt.Graphics;
-import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
-import java.awt.Shape;
import java.awt.Window;
import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
@@ -71,7 +69,6 @@ import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.beans.VetoableChangeSupport;
import java.io.Serializable;
-import java.util.ArrayList;
import java.util.EventListener;
import java.util.Hashtable;
import java.util.Locale;
@@ -684,7 +681,7 @@ public abstract class JComponent extends Container implements Serializable
* Indicates whether the current paint call is already double buffered or
* not.
*/
- static boolean isPaintingDoubleBuffered = false;
+ static boolean paintingDoubleBuffered = false;
/**
* Indicates whether we are calling paintDoubleBuffered() from
@@ -1849,7 +1846,7 @@ public abstract class JComponent extends Container implements Serializable
// buffer. When this method completes, the call stack unwinds back to
// paintDoubleBuffered, where the buffer contents is finally drawn to the
// screen.
- if (!isPaintingDoubleBuffered && isDoubleBuffered()
+ if (!paintingDoubleBuffered && isDoubleBuffered()
&& rm.isDoubleBufferingEnabled())
{
Rectangle clip = g.getClipBounds();
@@ -1940,227 +1937,77 @@ public abstract class JComponent extends Container implements Serializable
{
if (getComponentCount() > 0)
{
- if (isOptimizedDrawingEnabled())
- paintChildrenOptimized(g);
- else
- paintChildrenWithOverlap(g);
- }
- }
-
- /**
- * Paints the children of this JComponent in the case when the component
- * is not marked as optimizedDrawingEnabled, that means the container cannot
- * guarantee that it's children are tiled. For this case we must
- * perform a more complex optimization to determine the minimal rectangle
- * to be painted for each child component.
- *
- * @param g the graphics context to use
- */
- private void paintChildrenWithOverlap(Graphics g)
- {
- Shape originalClip = g.getClip();
- Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache);
- g.clipRect(inner.x, inner.y, inner.width, inner.height);
-
- // Find the rectangles that need to be painted for each child component.
- // We push on this list arrays that have the Rectangles to be painted as
- // the first elements and the component to be painted as the last one.
- // Later we go through that list in reverse order and paint the rectangles.
- int numChildren = getComponentCount();
- ArrayList paintRegions = new ArrayList(numChildren);
- ArrayList paintRectangles = new ArrayList();
- ArrayList newPaintRects = new ArrayList();
- paintRectangles.add(g.getClipBounds());
- ArrayList componentRectangles = new ArrayList();
-
- // Go through children from top to bottom and find out their paint
- // rectangles.
- for (int index = 0; paintRectangles.size() > 0 && index < numChildren; index++)
- {
- Component comp = getComponent(index);
- if (! comp.isVisible() || ! comp.isLightweight())
- continue;
-
- Rectangle compBounds = comp.getBounds();
- boolean isOpaque = comp.isOpaque();
-
- // Add all the current paint rectangles that intersect with the
- // component to the component's paint rectangle array.
- for (int i = paintRectangles.size() - 1; i >= 0; i--)
+ // Need to lock the tree to avoid problems with AWT and concurrency.
+ synchronized (getTreeLock())
{
- Rectangle r = (Rectangle) paintRectangles.get(i);
- if (r.intersects(compBounds))
+ for (int i = getComponentCount() - 1; i >= 0; i--)
{
- Rectangle compRect = r.intersection(compBounds);
- componentRectangles.add(compRect);
- // If the component is opaque, split up each paint rect and
- // add paintRect - compBounds to the newPaintRects array.
- if (isOpaque)
+ Component child = getComponent(i);
+ if (child != null && child.isLightweight()
+ && child.isVisible())
{
- int x, y, w, h;
- Rectangle rect = new Rectangle();
-
- // The north rectangle.
- x = Math.max(compBounds.x, r.x);
- y = r.y;
- w = Math.min(compBounds.width, r.width + r.x - x);
- h = compBounds.y - r.y;
- rect.setBounds(x, y, w, h);
- if (! rect.isEmpty())
- {
- newPaintRects.add(rect);
- rect = new Rectangle();
- }
-
- // The south rectangle.
- x = Math.max(compBounds.x, r.x);
- y = compBounds.y + compBounds.height;
- w = Math.min(compBounds.width, r.width + r.x - x);
- h = r.height - (compBounds.y - r.y) - compBounds.height;
- rect.setBounds(x, y, w, h);
- if (! rect.isEmpty())
+ int cx = child.getX();
+ int cy = child.getY();
+ int cw = child.getWidth();
+ int ch = child.getHeight();
+ if (g.hitClip(cx, cy, cw, ch))
{
- newPaintRects.add(rect);
- rect = new Rectangle();
+ if ((! isOptimizedDrawingEnabled()) && i > 0)
+ {
+ // Check if the child is completely obscured.
+ Rectangle clip = g.getClipBounds(); // A copy.
+ SwingUtilities.computeIntersection(cx, cy, cw, ch,
+ clip);
+ if (isCompletelyObscured(i, clip))
+ continue; // Continues the for-loop.
+ }
+ Graphics cg = g.create(cx, cy, cw, ch);
+ cg.setColor(child.getForeground());
+ cg.setFont(child.getFont());
+ try
+ {
+ child.paint(cg);
+ }
+ finally
+ {
+ cg.dispose();
+ }
}
-
- // The west rectangle.
- x = r.x;
- y = r.y;
- w = compBounds.x - r.x;
- h = r.height;
- rect.setBounds(x, y, w, h);
- if (! rect.isEmpty())
- {
- newPaintRects.add(rect);
- rect = new Rectangle();
- }
-
- // The east rectangle.
- x = compBounds.x + compBounds.width;
- y = r.y;
- w = r.width - (compBounds.x - r.x) - compBounds.width;
- h = r.height;
- rect.setBounds(x, y, w, h);
- if (! rect.isEmpty())
- {
- newPaintRects.add(rect);
- }
- }
- else
- {
- // Not opaque, need to reuse the current paint rectangles
- // for the next component.
- newPaintRects.add(r);
}
-
}
- else
- {
- newPaintRects.add(r);
- }
- }
-
- // Replace the paintRectangles with the new split up
- // paintRectangles.
- paintRectangles.clear();
- paintRectangles.addAll(newPaintRects);
- newPaintRects.clear();
-
- // Store paint rectangles if there are any for the current component.
- int compRectsSize = componentRectangles.size();
- if (compRectsSize > 0)
- {
- componentRectangles.add(comp);
- paintRegions.add(componentRectangles);
- componentRectangles = new ArrayList();
}
}
-
- // paintingTile becomes true just before we start painting the component's
- // children.
- paintingTile = true;
-
- // We must go through the painting regions backwards, because the
- // topmost components have been added first, followed by the components
- // below.
- int prEndIndex = paintRegions.size() - 1;
- for (int i = prEndIndex; i >= 0; i--)
- {
- // paintingTile must be set to false before we begin to start painting
- // the last tile.
- if (i == 0)
- paintingTile = false;
-
- ArrayList paintingRects = (ArrayList) paintRegions.get(i);
- // The last element is always the component.
- Component c = (Component) paintingRects.get(paintingRects.size() - 1);
- int endIndex = paintingRects.size() - 2;
- for (int j = 0; j <= endIndex; j++)
- {
- Rectangle cBounds = c.getBounds();
- Rectangle bounds = (Rectangle) paintingRects.get(j);
- Rectangle oldClip = g.getClipBounds();
- if (oldClip == null)
- oldClip = bounds;
-
- boolean translated = false;
- try
- {
- g.setClip(bounds);
- g.translate(cBounds.x, cBounds.y);
- translated = true;
- c.paint(g);
- }
- finally
- {
- if (translated)
- g.translate(-cBounds.x, -cBounds.y);
- g.setClip(oldClip);
- }
- }
- }
- g.setClip(originalClip);
}
/**
- * Paints the children of this container when it is marked as
- * optimizedDrawingEnabled. In this case the container can guarantee that
- * it's children are tiled, which allows for a much more efficient
- * algorithm to determine the minimum rectangles to be painted for
- * each child.
+ * Determines if a region of a child component is completely obscured by one
+ * of its siblings.
*
- * @param g the graphics context to use
+ * @param index the index of the child component
+ * @param rect the region to check
+ *
+ * @return <code>true</code> if the region is completely obscured by a
+ * sibling, <code>false</code> otherwise
*/
- private void paintChildrenOptimized(Graphics g)
+ private boolean isCompletelyObscured(int index, Rectangle rect)
{
- Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache);
- g.clipRect(inner.x, inner.y, inner.width, inner.height);
-
- // paintingTile becomes true just before we start painting the component's
- // children.
- paintingTile = true;
- int numChildren = getComponentCount();
- for (int i = numChildren - 1; i >= 0; i--) //children.length; i++)
+ boolean obscured = false;
+ for (int i = index - 1; i >= 0 && obscured == false; i--)
{
- Component child = getComponent(i);
- // paintingTile must be set to false before we begin to start painting
- // the last tile.
- if (i == numChildren - 1)
- paintingTile = false;
-
- if (!child.isVisible() || ! child.isLightweight())
- continue;
-
- Rectangle bounds = child.getBounds(rectCache);
- if (!g.hitClip(bounds.x, bounds.y, bounds.width, bounds.height))
- continue;
-
- Graphics g2 = g.create(bounds.x, bounds.y, bounds.width,
- bounds.height);
- child.paint(g2);
- g2.dispose();
+ Component sib = getComponent(i);
+ if (sib.isVisible())
+ {
+ Rectangle sibRect = sib.getBounds(rectCache);
+ if (sib.isOpaque() && rect.x >= sibRect.x
+ && (rect.x + rect.width) <= (sibRect.x + sibRect.width)
+ && rect.y >= sibRect.y
+ && (rect.y + rect.height) <= (sibRect.y + sibRect.height))
+ {
+ obscured = true;
+ }
+ }
}
+ return obscured;
}
/**
@@ -2180,12 +2027,15 @@ public abstract class JComponent extends Container implements Serializable
{
if (ui != null)
{
- Graphics g2 = g;
- if (!(g instanceof Graphics2D))
- g2 = g.create();
- ui.update(g2, this);
- if (!(g instanceof Graphics2D))
- g2.dispose();
+ Graphics g2 = g.create();
+ try
+ {
+ ui.update(g2, this);
+ }
+ finally
+ {
+ g2.dispose();
+ }
}
}
@@ -2295,7 +2145,7 @@ public abstract class JComponent extends Container implements Serializable
clipAndTranslateGraphics(root, this, g2);
g2.clipRect(r.x, r.y, r.width, r.height);
g2 = getComponentGraphics(g2);
- isPaintingDoubleBuffered = true;
+ paintingDoubleBuffered = true;
try
{
if (isRepainting) // Called from paintImmediately, go through paint().
@@ -2309,7 +2159,7 @@ public abstract class JComponent extends Container implements Serializable
}
finally
{
- isPaintingDoubleBuffered = false;
+ paintingDoubleBuffered = false;
g2.dispose();
}
@@ -2329,11 +2179,16 @@ public abstract class JComponent extends Container implements Serializable
private void clipAndTranslateGraphics(Component root, Component target,
Graphics g)
{
- Component parent = target.getParent();
- if (parent != root)
- clipAndTranslateGraphics(root, parent, g);
-
- g.translate(target.getX(), target.getY());
+ Component parent = target;
+ int deltaX = 0;
+ int deltaY = 0;
+ while (parent != root)
+ {
+ deltaX += parent.getX();
+ deltaY += parent.getY();
+ parent = parent.getParent();
+ }
+ g.translate(deltaX, deltaY);
g.clipRect(0, 0, target.getWidth(), target.getHeight());
}
@@ -2726,10 +2581,11 @@ public abstract class JComponent extends Container implements Serializable
if (isEnabled())
{
Action act = null;
+ Object cmd = null;
InputMap map = getInputMap(condition);
if (map != null)
{
- Object cmd = map.get(ks);
+ cmd = map.get(ks);
if (cmd != null)
{
if (cmd instanceof ActionListenerProxy)
@@ -2739,7 +2595,23 @@ public abstract class JComponent extends Container implements Serializable
}
}
if (act != null && act.isEnabled())
- return SwingUtilities.notifyAction(act, ks, e, this, e.getModifiers());
+ {
+ // Need to synchronize here so we don't get in trouble with
+ // our __command__ hack.
+ synchronized (act)
+ {
+ // We add the command as value to the action, so that
+ // the action can later determine the command with which it
+ // was called. This is undocumented, but shouldn't affect
+ // compatibility. It allows us to use only one Action instance
+ // to do the work for all components of one type, instead of
+ // having loads of small Actions. This effectivly saves startup
+ // time of Swing.
+ act.putValue("__command__", cmd);
+ return SwingUtilities.notifyAction(act, ks, e, this,
+ e.getModifiers());
+ }
+ }
}
return false;
}
diff --git a/javax/swing/JEditorPane.java b/javax/swing/JEditorPane.java
index 4ae3c5a1c..2dcaafc27 100644
--- a/javax/swing/JEditorPane.java
+++ b/javax/swing/JEditorPane.java
@@ -717,7 +717,8 @@ public class JEditorPane extends JTextComponent
// and has a height > minimum UI height.
Container parent = getParent();
return parent instanceof JViewport
- && parent.getHeight() > getUI().getMinimumSize(this).height;
+ && parent.getHeight() >= getUI().getMinimumSize(this).height
+ && parent.getHeight() <= getUI().getMaximumSize(this).height;
}
/**
diff --git a/javax/swing/JFileChooser.java b/javax/swing/JFileChooser.java
index 64f9bd0f4..a508b8fcb 100644
--- a/javax/swing/JFileChooser.java
+++ b/javax/swing/JFileChooser.java
@@ -43,6 +43,8 @@ import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowAdapter;
import java.beans.PropertyChangeEvent;
import java.io.File;
import java.util.ArrayList;
@@ -351,7 +353,7 @@ public class JFileChooser extends JComponent implements Accessible
* The file selection mode.
* @see #setFileSelectionMode(int)
*/
- private int fileSelectionMode = FILES_AND_DIRECTORIES;
+ private int fileSelectionMode = FILES_ONLY;
/**
* The file view.
@@ -744,10 +746,16 @@ public class JFileChooser extends JComponent implements Accessible
JDialog dialog = new JDialog(toUse);
setSelectedFile(null);
dialog.getContentPane().add(this);
+ dialog.addWindowListener( new WindowAdapter()
+ {
+ public void windowClosing(WindowEvent e)
+ {
+ cancelSelection();
+ }
+ });
dialog.setModal(true);
dialog.invalidate();
dialog.repaint();
-
return dialog;
}
diff --git a/javax/swing/JList.java b/javax/swing/JList.java
index 6a98770ee..98b299044 100644
--- a/javax/swing/JList.java
+++ b/javax/swing/JList.java
@@ -1935,72 +1935,74 @@ public class JList extends JComponent implements Accessible, Scrollable
public int getScrollableUnitIncrement(Rectangle visibleRect,
int orientation, int direction)
{
- ListUI lui = this.getUI();
+ int unit = -1;
if (orientation == SwingConstants.VERTICAL)
{
- if (direction > 0)
+ int row = getFirstVisibleIndex();
+ if (row == -1)
+ unit = 0;
+ else if (direction > 0)
{
- // Scrolling down
- Point bottomLeft = new Point(visibleRect.x,
- visibleRect.y + visibleRect.height);
- int curIdx = lui.locationToIndex(this, bottomLeft);
- Rectangle curBounds = lui.getCellBounds(this, curIdx, curIdx);
- if (curBounds.y + curBounds.height == bottomLeft.y)
+ // Scrolling down.
+ Rectangle bounds = getCellBounds(row, row);
+ if (bounds != null)
+ unit = bounds.height - (visibleRect.y - bounds.y);
+ else
+ unit = 0;
+ }
+ else
+ {
+ // Scrolling up.
+ Rectangle bounds = getCellBounds(row, row);
+ // First row.
+ if (row == 0 && bounds.y == visibleRect.y)
+ unit = 0; // No need to scroll.
+ else if (bounds.y == visibleRect.y)
{
- // we are at the exact bottom of the current cell, so we
- // are being asked to scroll to the end of the next one
- if (curIdx + 1 < model.getSize())
- {
- // there *is* a next item in the list
- Rectangle nxtBounds = lui.getCellBounds(this, curIdx + 1, curIdx + 1);
- return nxtBounds.height;
- }
+ // Scroll to previous row.
+ Point loc = bounds.getLocation();
+ loc.y--;
+ int prev = locationToIndex(loc);
+ Rectangle prevR = getCellBounds(prev, prev);
+ if (prevR == null || prevR.y >= bounds.y)
+ unit = 0; // For multicolumn lists.
else
- {
- // no next item, no advance possible
- return 0;
- }
+ unit = prevR.height;
}
else
- {
- // we are part way through an existing cell, so we are being
- // asked to scroll to the bottom of it
- return (curBounds.y + curBounds.height) - bottomLeft.y;
- }
+ unit = visibleRect.y - bounds.y;
}
- else
+ }
+ else if (orientation == SwingConstants.HORIZONTAL && getLayoutOrientation() != VERTICAL)
+ {
+ // Horizontal scrolling.
+ int i = locationToIndex(visibleRect.getLocation());
+ if (i != -1)
{
- // scrolling up
- Point topLeft = new Point(visibleRect.x, visibleRect.y);
- int curIdx = lui.locationToIndex(this, topLeft);
- Rectangle curBounds = lui.getCellBounds(this, curIdx, curIdx);
- if (curBounds.y == topLeft.y)
+ Rectangle b = getCellBounds(i, i);
+ if (b != null)
{
- // we are at the exact top of the current cell, so we
- // are being asked to scroll to the top of the previous one
- if (curIdx > 0)
+ if (b.x != visibleRect.x)
{
- // there *is* a previous item in the list
- Rectangle nxtBounds = lui.getCellBounds(this, curIdx - 1, curIdx - 1);
- return -nxtBounds.height;
+ if (direction < 0)
+ unit = Math.abs(b.x - visibleRect.x);
+ else
+ unit = b.width + b.x - visibleRect.x;
}
else
- {
- // no previous item, no advance possible
- return 0;
- }
+ unit = b.width;
}
- else
- {
- // we are part way through an existing cell, so we are being
- // asked to scroll to the top of it
- return curBounds.y - topLeft.y;
- }
}
}
- // FIXME: handle horizontal scrolling (also wrapping?)
- return 1;
+ if (unit == -1)
+ {
+ // This fallback seems to be used by the RI for the degenerate cases
+ // not covered above.
+ Font f = getFont();
+ unit = f != null ? f.getSize() : 1;
+ }
+ return unit;
}
/**
@@ -2029,10 +2031,120 @@ public class JList extends JComponent implements Accessible, Scrollable
public int getScrollableBlockIncrement(Rectangle visibleRect,
int orientation, int direction)
{
- if (orientation == VERTICAL)
- return visibleRect.height * direction;
- else
- return visibleRect.width * direction;
+ int block = -1;
+ if (orientation == SwingConstants.VERTICAL)
+ {
+ // Default block scroll. Special cases are handled below for
+ // better usability.
+ block = visibleRect.height;
+ if (direction > 0)
+ {
+ // Scroll down.
+ // Scroll so that after scrolling the last line aligns with
+ // the lower boundary of the visible area.
+ Point p = new Point(visibleRect.x,
+ visibleRect.y + visibleRect.height - 1);
+ int last = locationToIndex(p);
+ if (last != -1)
+ {
+ Rectangle lastR = getCellBounds(last, last);
+ if (lastR != null)
+ {
+ block = lastR.y - visibleRect.y;
+ if (block == 0&& last < getModel().getSize() - 1)
+ block = lastR.height;
+ }
+ }
+ }
+ else
+ {
+ // Scroll up.
+ // Scroll so that after scrolling the first line aligns with
+ // the upper boundary of the visible area.
+ Point p = new Point(visibleRect.x,
+ visibleRect.y - visibleRect.height);
+ int newFirst = locationToIndex(p);
+ if (newFirst != -1)
+ {
+ int first = getFirstVisibleIndex();
+ if (first == -1)
+ first = locationToIndex(visibleRect.getLocation());
+ Rectangle newFirstR = getCellBounds(newFirst, newFirst);
+ Rectangle firstR = getCellBounds(first, first);
+ if (newFirstR != null && firstR != null)
+ {
+ // Search first item that would left the current first
+ // item visible when scrolled to.
+ while (newFirstR.y + visibleRect.height
+ < firstR.y + firstR.height
+ && newFirstR.y < firstR.y)
+ {
+ newFirst++;
+ newFirstR = getCellBounds(newFirst, newFirst);
+ }
+ block = visibleRect.y - newFirstR.y;
+ if (block <= 0 && newFirstR.y > 0)
+ {
+ newFirst--;
+ newFirstR = getCellBounds(newFirst, newFirst);
+ if (newFirstR != null)
+ block = visibleRect.y - newFirstR.y;
+ }
+ }
+ }
+ }
+ }
+ else if (orientation == SwingConstants.HORIZONTAL
+ && getLayoutOrientation() != VERTICAL)
+ {
+ // Default block increment. Special cases are handled below for
+ // better usability.
+ block = visibleRect.width;
+ if (direction > 0)
+ {
+ // Scroll right.
+ Point p = new Point(visibleRect.x + visibleRect.width + 1,
+ visibleRect.y);
+ int last = locationToIndex(p);
+ if (last != -1)
+ {
+ Rectangle lastR = getCellBounds(last, last);
+ if (lastR != null)
+ {
+ block = lastR.x - visibleRect.x;
+ if (block < 0)
+ block += lastR.width;
+ else if (block == 0 && last < getModel().getSize() - 1)
+ block = lastR.width;
+ }
+ }
+ }
+ else
+ {
+ // Scroll left.
+ Point p = new Point(visibleRect.x - visibleRect.width,
+ visibleRect.y);
+ int first = locationToIndex(p);
+ if (first != -1)
+ {
+ Rectangle firstR = getCellBounds(first, first);
+ if (firstR != null)
+ {
+ if (firstR.x < visibleRect.x - visibleRect.width)
+ {
+ if (firstR.x + firstR.width > visibleRect.x)
+ block = visibleRect.x - firstR.x;
+ else
+ block = visibleRect.x - firstR.x - firstR.width;
+ }
+ else
+ block = visibleRect.x - firstR.x;
+ }
+ }
+ }
+ }
+
+ return block;
}
/**
diff --git a/javax/swing/JMenu.java b/javax/swing/JMenu.java
index 0840509f9..9432865e5 100644
--- a/javax/swing/JMenu.java
+++ b/javax/swing/JMenu.java
@@ -40,7 +40,6 @@ package javax.swing;
import java.awt.Component;
import java.awt.Point;
-import java.awt.PopupMenu;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
@@ -54,6 +53,8 @@ import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleSelection;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import javax.swing.plaf.MenuItemUI;
@@ -72,6 +73,36 @@ import javax.swing.plaf.MenuItemUI;
*/
public class JMenu extends JMenuItem implements Accessible, MenuElement
{
+ /**
+ * Receives notifications when the JMenu's ButtonModel is changed and
+ * fires menuSelected or menuDeselected events when appropriate.
+ */
+ private class MenuChangeListener
+ implements ChangeListener
+ {
+ /**
+ * Indicates the last selected state.
+ */
+ private boolean selected;
+
+ /**
+ * Receives notification when the JMenu's ButtonModel changes.
+ */
+ public void stateChanged(ChangeEvent ev)
+ {
+ ButtonModel m = (ButtonModel) ev.getSource();
+ boolean s = m.isSelected();
+ if (s != selected)
+ {
+ if (s)
+ fireMenuSelected();
+ else
+ fireMenuDeselected();
+ selected = s;
+ }
+ }
+ }
+
private static final long serialVersionUID = 4227225638931828014L;
/** A Popup menu associated with this menu, which pops up when menu is selected */
@@ -93,13 +124,19 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
private Point menuLocation;
/**
+ * The ChangeListener for the ButtonModel.
+ *
+ * @see MenuChangeListener
+ */
+ private ChangeListener menuChangeListener;
+
+ /**
* Creates a new JMenu object.
*/
public JMenu()
{
super();
setOpaque(false);
- setDelay(200);
}
/**
@@ -113,7 +150,6 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
popupMenu = new JPopupMenu();
popupMenu.setInvoker(this);
setOpaque(false);
- setDelay(200);
}
/**
@@ -129,7 +165,6 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
popupMenu = new JPopupMenu();
popupMenu.setInvoker(this);
setOpaque(false);
- setDelay(200);
}
/**
@@ -143,7 +178,6 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
{
// FIXME: tearoff not implemented
this(text);
- setDelay(200);
}
/**
@@ -193,7 +227,7 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
*/
public JMenuItem add(String text)
{
- return getPopupMenu().add(text);
+ return add(new JMenuItem(text));
}
/**
@@ -205,7 +239,10 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
*/
public JMenuItem add(Action action)
{
- return getPopupMenu().add(action);
+ JMenuItem i = createActionComponent(action);
+ i.setAction(action);
+ add(i);
+ return i;
}
/**
@@ -328,7 +365,18 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
*/
public void setModel(ButtonModel model)
{
+ ButtonModel oldModel = getModel();
+ if (oldModel != null && changeListener != null)
+ oldModel.removeChangeListener(changeListener);
+
super.setModel(model);
+
+ if (model != null)
+ {
+ if (changeListener == null)
+ changeListener = new MenuChangeListener();
+ model.addChangeListener(changeListener);
+ }
}
/**
@@ -342,63 +390,6 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
}
/**
- * A helper method to handle setSelected calls from both mouse events and
- * direct calls to setSelected. Direct calls shouldn't expand the popup
- * menu and should select the JMenu even if it is disabled. Mouse events
- * only select the JMenu if it is enabled and should expand the popup menu
- * associated with this JMenu.
- * @param selected whether or not the JMenu was selected
- * @param menuEnabled whether or not selecting the menu is "enabled". This
- * is always true for direct calls, and is set to isEnabled() for mouse
- * based calls.
- * @param showMenu whether or not to show the popup menu
- */
- private void setSelectedHelper(boolean selected, boolean menuEnabled, boolean showMenu)
- {
- // If menu is selected and enabled, activates the menu and
- // displays associated popup.
- if (selected && menuEnabled)
- {
- super.setArmed(true);
- super.setSelected(true);
-
- // FIXME: The popup menu should be shown on the screen after certain
- // number of seconds pass. The 'delay' property of this menu indicates
- // this amount of seconds. 'delay' property is 0 by default.
- if (isShowing())
- {
- fireMenuSelected();
-
- int x = 0;
- int y = 0;
- if (showMenu)
- if (menuLocation == null)
- {
- // Calculate correct position of the popup. Note that location of the popup
- // passed to show() should be relative to the popup's invoker
- if (isTopLevelMenu())
- y = this.getHeight();
- else
- x = this.getWidth();
- getPopupMenu().show(this, x, y);
- }
- else
- {
- getPopupMenu().show(this, menuLocation.x, menuLocation.y);
- }
- }
- }
-
- else
- {
- super.setSelected(false);
- super.setArmed(false);
- fireMenuDeselected();
- getPopupMenu().setVisible(false);
- }
- }
-
- /**
* Changes this menu selected state if selected is true and false otherwise
* This method fires menuEvents to menu's registered listeners.
*
@@ -406,7 +397,9 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
*/
public void setSelected(boolean selected)
{
- setSelectedHelper(selected, true, false);
+ ButtonModel m = getModel();
+ if (selected != m.isSelected())
+ m.setSelected(selected);
}
/**
@@ -427,8 +420,17 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
*/
public void setPopupMenuVisible(boolean popup)
{
- if (getModel().isEnabled())
- getPopupMenu().setVisible(popup);
+ if (popup != isPopupMenuVisible() && (isEnabled() || ! popup))
+ {
+ if (popup && isShowing())
+ {
+ // Set location as determined by getPopupLocation().
+ Point loc = getPopupMenuOrigin();
+ getPopupMenu().show(this, loc.x, loc.y);
+ }
+ else
+ getPopupMenu().setVisible(false);
+ }
}
/**
@@ -438,12 +440,22 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
*/
protected Point getPopupMenuOrigin()
{
+ Point point;
+
// if menu in the menu bar
if (isTopLevelMenu())
- return new Point(0, this.getHeight());
+ point = new Point(0, this.getHeight());
- // if submenu
- return new Point(this.getWidth(), 0);
+ // if submenu
+ else
+ {
+ int xOffset = UIManager.getInt("Menu.submenuPopupOffsetX");
+ int yOffset = UIManager.getInt("Menu.submenuPopupOffsetY");
+ int x = getWidth() + xOffset;
+ int y = yOffset;
+ point = new Point(x, y);
+ }
+ return point;
}
/**
@@ -748,7 +760,7 @@ public class JMenu extends JMenuItem implements Accessible, MenuElement
{
// if this menu selection is true, then activate this menu and
// display popup associated with this menu
- setSelectedHelper(changed, isEnabled(), true);
+ setSelected(changed);
}
/**
diff --git a/javax/swing/JOptionPane.java b/javax/swing/JOptionPane.java
index f94905538..43caecd1a 100644
--- a/javax/swing/JOptionPane.java
+++ b/javax/swing/JOptionPane.java
@@ -48,6 +48,8 @@ import java.awt.MenuComponent;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseMotionAdapter;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
@@ -378,11 +380,49 @@ public class JOptionPane extends JComponent implements Accessible
dialog.setResizable(false);
dialog.pack();
dialog.setLocationRelativeTo(parentComponent);
-
+
+ addPropertyChangeListener(new ValuePropertyHandler(dialog));
return dialog;
}
/**
+ * Handles changes of the value property. Whenever this property changes,
+ * the JOptionPane dialog should be closed.
+ */
+ private static class ValuePropertyHandler
+ implements PropertyChangeListener
+ {
+ /**
+ * The dialog to close.
+ */
+ JDialog dialog;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param d the dialog to be closed
+ */
+ ValuePropertyHandler(JDialog d)
+ {
+ dialog = d;
+ }
+
+ /**
+ * Receives notification when any of the properties change.
+ */
+ public void propertyChange(PropertyChangeEvent p)
+ {
+ String prop = p.getPropertyName();
+ Object val = p.getNewValue();
+ if (prop.equals(VALUE_PROPERTY) && val != null
+ && val != UNINITIALIZED_VALUE)
+ {
+ dialog.setVisible(false);
+ }
+ }
+ }
+
+ /**
* This method creates a new JInternalFrame that is in the JLayeredPane
* which contains the parentComponent given. If no suitable JLayeredPane
* can be found from the parentComponent given, a RuntimeException will be
diff --git a/javax/swing/JPopupMenu.java b/javax/swing/JPopupMenu.java
index c7890ea0e..2e59d4767 100644
--- a/javax/swing/JPopupMenu.java
+++ b/javax/swing/JPopupMenu.java
@@ -120,7 +120,7 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement
private boolean lightWeightPopupEnabled;
/** SelectionModel that keeps track of menu selection. */
- private SingleSelectionModel selectionModel;
+ protected SingleSelectionModel selectionModel;
/* Popup that is used to display JPopupMenu */
private transient Popup popup;
@@ -820,7 +820,14 @@ public class JPopupMenu extends JComponent implements Accessible, MenuElement
*/
public void menuSelectionChanged(boolean changed)
{
- if (! changed)
+ if (invoker instanceof JMenu)
+ {
+ // We need to special case this since the JMenu calculates the
+ // position etc of the popup.
+ JMenu menu = (JMenu) invoker;
+ menu.setPopupMenuVisible(changed);
+ }
+ else if (! changed)
setVisible(false);
}
diff --git a/javax/swing/JTabbedPane.java b/javax/swing/JTabbedPane.java
index ee6af857e..a500b9264 100644
--- a/javax/swing/JTabbedPane.java
+++ b/javax/swing/JTabbedPane.java
@@ -760,11 +760,7 @@ public class JTabbedPane extends JComponent implements Serializable,
this.tabPlacement = tabPlacement;
layoutPolicy = tabLayoutPolicy;
- changeEvent = new ChangeEvent(this);
- changeListener = createChangeListener();
-
- model = new DefaultSingleSelectionModel();
- model.addChangeListener(changeListener);
+ setModel(new DefaultSingleSelectionModel());
updateUI();
}
@@ -877,16 +873,24 @@ public class JTabbedPane extends JComponent implements Serializable,
/**
* This method changes the model property of the JTabbedPane.
*
- * @param model The new model to use with the JTabbedPane.
+ * @param m The new model to use with the JTabbedPane.
*/
- public void setModel(SingleSelectionModel model)
+ public void setModel(SingleSelectionModel m)
{
- if (model != this.model)
+ if (m != model)
{
SingleSelectionModel oldModel = this.model;
- this.model.removeChangeListener(changeListener);
- this.model = model;
- this.model.addChangeListener(changeListener);
+ if (oldModel != null && changeListener != null)
+ oldModel.removeChangeListener(changeListener);
+
+ model = m;
+
+ if (model != null)
+ {
+ if (changeListener != null)
+ changeListener = createChangeListener();
+ model.addChangeListener(changeListener);
+ }
firePropertyChange("model", oldModel, this.model);
}
}
@@ -990,6 +994,8 @@ public class JTabbedPane extends JComponent implements Serializable,
checkIndex(index, -1, tabs.size());
if (index != getSelectedIndex())
{
+ // Hiding and showing the involved components
+ // is done by the JTabbedPane's UI.
model.setSelectedIndex(index);
}
}
@@ -1247,7 +1253,32 @@ public class JTabbedPane extends JComponent implements Serializable,
*/
public void remove(Component component)
{
- super.remove(component);
+ // Since components implementing UIResource
+ // are not added as regular tabs by the add()
+ // methods we have to take special care when
+ // removing these object. Especially
+ // Container.remove(Component) cannot be used
+ // because it will call JTabbedPane.remove(int)
+ // later which is overridden and can only
+ // handle tab components.
+ // This implementation can even cope with a
+ // situation that someone called insertTab()
+ // with a component that implements UIResource.
+ int index = indexOfComponent(component);
+
+ // If the component is not a tab component
+ // find out its Container-given index
+ // and call that class' implementation
+ // directly.
+ if (index == -1)
+ {
+ Component[] cs = getComponents();
+ for (int i = 0; i< cs.length; i++)
+ if (cs[i] == component)
+ super.remove(i);
+ }
+ else
+ removeTabAt(index);
}
/**
@@ -1257,7 +1288,6 @@ public class JTabbedPane extends JComponent implements Serializable,
*/
public void remove(int index)
{
- super.remove(index);
removeTabAt(index);
}
diff --git a/javax/swing/JTable.java b/javax/swing/JTable.java
index 855530881..0b9467f33 100644
--- a/javax/swing/JTable.java
+++ b/javax/swing/JTable.java
@@ -2922,56 +2922,189 @@ public class JTable
{
// update the column model from the table model if the structure has
// changed and the flag autoCreateColumnsFromModel is set
- if ((event == null || (event.getFirstRow() == TableModelEvent.HEADER_ROW))
- && autoCreateColumnsFromModel)
+ if (event == null || (event.getFirstRow() == TableModelEvent.HEADER_ROW))
+ handleCompleteChange(event);
+ else if (event.getType() == TableModelEvent.INSERT)
+ handleInsert(event);
+ else if (event.getType() == TableModelEvent.DELETE)
+ handleDelete(event);
+ else
+ handleUpdate(event);
+ }
+
+ /**
+ * Handles a request for complete relayout. This is the case when
+ * event.getFirstRow() == TableModelEvent.HEADER_ROW.
+ *
+ * @param ev the table model event
+ */
+ private void handleCompleteChange(TableModelEvent ev)
+ {
+ clearSelection();
+ checkSelection();
+ rowHeights = null;
+ if (getAutoCreateColumnsFromModel())
+ createDefaultColumnsFromModel();
+ else
+ resizeAndRepaint();
+ }
+
+ /**
+ * Handles table model insertions.
+ *
+ * @param ev the table model event
+ */
+ private void handleInsert(TableModelEvent ev)
+ {
+ // Sync selection model with data model.
+ int first = ev.getFirstRow();
+ if (first < 0)
+ first = 0;
+ int last = ev.getLastRow();
+ if (last < 0)
+ last = getRowCount() - 1;
+ selectionModel.insertIndexInterval(first, last - first + 1, true);
+ checkSelection();
+
+ // For variable height rows we must update the SizeSequence thing.
+ if (rowHeights != null)
{
- rowHeights = null;
- if (getAutoCreateColumnsFromModel())
- createDefaultColumnsFromModel();
- resizeAndRepaint();
- return;
+ rowHeights.insertEntries(first, last - first + 1, rowHeight);
+ // TODO: We repaint the whole thing when the rows have variable
+ // heights. We might want to handle this better though.
+ repaint();
+ }
+ else
+ {
+ // Repaint the dirty region and revalidate.
+ int rowHeight = getRowHeight();
+ Rectangle dirty = new Rectangle(0, first * rowHeight,
+ getColumnModel().getTotalColumnWidth(),
+ (getRowCount() - first) * rowHeight);
+ repaint(dirty);
}
+ revalidate();
+ }
+
+ /**
+ * Handles table model deletions.
+ *
+ * @param ev the table model event
+ */
+ private void handleDelete(TableModelEvent ev)
+ {
+ // Sync selection model with data model.
+ int first = ev.getFirstRow();
+ if (first < 0)
+ first = 0;
+ int last = ev.getLastRow();
+ if (last < 0)
+ last = getRowCount() - 1;
+
+ selectionModel.removeIndexInterval(first, last);
+
+ checkSelection();
+
+ if (dataModel.getRowCount() == 0)
+ clearSelection();
- // If the structure changes, we need to revalidate, since that might
- // affect the size parameters of the JTable. Otherwise we only need
- // to perform a repaint to update the view.
- if (event == null || event.getType() == TableModelEvent.INSERT)
+ // For variable height rows we must update the SizeSequence thing.
+ if (rowHeights != null)
+ {
+ rowHeights.removeEntries(first, last - first + 1);
+ // TODO: We repaint the whole thing when the rows have variable
+ // heights. We might want to handle this better though.
+ repaint();
+ }
+ else
{
- // Sync selection model with data model.
- if (event != null)
+ // Repaint the dirty region and revalidate.
+ int rowHeight = getRowHeight();
+ int oldRowCount = getRowCount() + last - first + 1;
+ Rectangle dirty = new Rectangle(0, first * rowHeight,
+ getColumnModel().getTotalColumnWidth(),
+ (oldRowCount - first) * rowHeight);
+ repaint(dirty);
+ }
+ revalidate();
+ }
+
+ /**
+ * Handles table model updates without structural changes.
+ *
+ * @param ev the table model event
+ */
+ private void handleUpdate(TableModelEvent ev)
+ {
+ if (rowHeights == null)
+ {
+ // Some cells have been changed without changing the structure.
+ // Figure out the dirty rectangle and repaint.
+ int firstRow = ev.getFirstRow();
+ int lastRow = ev.getLastRow();
+ int col = ev.getColumn();
+ Rectangle dirty;
+ if (col == TableModelEvent.ALL_COLUMNS)
{
- int first = event.getFirstRow();
- if (first < 0)
- first = 0;
- int last = event.getLastRow();
- if (last < 0)
- last = getRowCount() - 1;
- selectionModel.insertIndexInterval(first, last - first + 1, true);
- if (rowHeights != null)
- rowHeights.insertEntries(first, last - first + 1, rowHeight);
+ // All columns changed.
+ dirty = new Rectangle(0, firstRow * getRowHeight(),
+ getColumnModel().getTotalColumnWidth(), 0);
}
- revalidate();
+ else
+ {
+ // Only one cell or column of cells changed.
+ // We need to convert to view column first.
+ int column = convertColumnIndexToModel(col);
+ dirty = getCellRect(firstRow, column, false);
+ }
+
+ // Now adjust the height of the dirty region.
+ dirty.height = (lastRow + 1) * getRowHeight();
+ // .. and repaint.
+ repaint(dirty);
+ }
+ else
+ {
+ // TODO: We repaint the whole thing when the rows have variable
+ // heights. We might want to handle this better though.
+ repaint();
}
- if (event == null || event.getType() == TableModelEvent.DELETE)
+ }
+
+ /**
+ * Helper method for adjusting the lead and anchor indices when the
+ * table structure changed. This sets the lead and anchor to -1 if there's
+ * no more rows, or set them to 0 when they were at -1 and there are actually
+ * some rows now.
+ */
+ private void checkSelection()
+ {
+ TableModel m = getModel();
+ ListSelectionModel sm = selectionModel;
+ if (m != null)
{
- // Sync selection model with data model.
- if (event != null)
+ int lead = sm.getLeadSelectionIndex();
+ int c = m.getRowCount();
+ if (c == 0 && lead != -1)
{
- int first = event.getFirstRow();
- if (first < 0)
- first = 0;
- int last = event.getLastRow();
- if (last < 0)
- last = getRowCount() - 1;
- selectionModel.removeIndexInterval(first, last);
- if (rowHeights != null)
- rowHeights.removeEntries(first, last - first + 1);
+ // No rows in the model, reset lead and anchor to -1.
+ sm.setValueIsAdjusting(true);
+ sm.setAnchorSelectionIndex(-1);
+ sm.setLeadSelectionIndex(-1);
+ sm.setValueIsAdjusting(false);
}
- if (dataModel.getRowCount() == 0)
- clearSelection();
- revalidate();
+ else if (c != 0 && lead == -1)
+ {
+ // We have rows, but no lead/anchor. Set them to 0. We
+ // do a little trick here so that the actual selection is not
+ // touched.
+ if (sm.isSelectedIndex(0))
+ sm.addSelectionInterval(0, 0);
+ else
+ sm.removeSelectionInterval(0, 0);
+ }
+ // Nothing to do in the other cases.
}
- repaint();
}
/**
@@ -3170,10 +3303,21 @@ public class JTable
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction)
{
- if (orientation == SwingConstants.VERTICAL)
- return visibleRect.height * direction;
+ int block;
+ if (orientation == SwingConstants.HORIZONTAL)
+ {
+ block = visibleRect.width;
+ }
else
- return visibleRect.width * direction;
+ {
+ int rowHeight = getRowHeight();
+ if (rowHeight > 0)
+ block = Math.max(rowHeight, // Little hack for useful rounding.
+ (visibleRect.height / rowHeight) * rowHeight);
+ else
+ block = visibleRect.height;
+ }
+ return block;
}
/**
@@ -3217,19 +3361,12 @@ public class JTable
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
int direction)
{
- int h = (rowHeight + rowMargin);
- int delta = h * direction;
-
- // Round so that the top would start from the row boundary
- if (orientation == SwingConstants.VERTICAL)
- {
- // Completely expose the top row
- int near = ((visibleRect.y + delta + h / 2) / h) * h;
- int diff = visibleRect.y + delta - near;
- delta -= diff;
- }
- return delta;
- // TODO when scrollng horizontally, scroll into the column boundary.
+ int unit;
+ if (orientation == SwingConstants.HORIZONTAL)
+ unit = 100;
+ else
+ unit = getRowHeight();
+ return unit;
}
/**
@@ -3468,6 +3605,8 @@ public class JTable
* Get the value of the {@link #rowSelectionAllowed} property.
*
* @return The current value of the property
+ *
+ * @see #setRowSelectionAllowed(boolean)
*/
public boolean getRowSelectionAllowed()
{
@@ -3621,6 +3760,8 @@ public class JTable
* Get the value of the <code>columnSelectionAllowed</code> property.
*
* @return The current value of the columnSelectionAllowed property
+ *
+ * @see #setColumnSelectionAllowed(boolean)
*/
public boolean getColumnSelectionAllowed()
{
@@ -3874,11 +4015,17 @@ public class JTable
* Set the value of the {@link #rowSelectionAllowed} property.
*
* @param r The new value of the rowSelectionAllowed property
+ *
+ * @see #getRowSelectionAllowed()
*/
public void setRowSelectionAllowed(boolean r)
{
- rowSelectionAllowed = r;
- repaint();
+ if (rowSelectionAllowed != r)
+ {
+ rowSelectionAllowed = r;
+ firePropertyChange("rowSelectionAllowed", !r, r);
+ repaint();
+ }
}
/**
@@ -3988,11 +4135,17 @@ public class JTable
* Set the value of the <code>columnSelectionAllowed</code> property.
*
* @param c The new value of the property
+ *
+ * @see #getColumnSelectionAllowed()
*/
public void setColumnSelectionAllowed(boolean c)
{
- getColumnModel().setColumnSelectionAllowed(c);
- repaint();
+ if (columnModel.getColumnSelectionAllowed() != c)
+ {
+ columnModel.setColumnSelectionAllowed(c);
+ firePropertyChange("columnSelectionAllowed", !c, c);
+ repaint();
+ }
}
/**
@@ -4014,6 +4167,7 @@ public class JTable
if (s != null)
s.addListSelectionListener(this);
selectionModel = s;
+ checkSelection();
}
/**
diff --git a/javax/swing/JTextPane.java b/javax/swing/JTextPane.java
index c0a5f80cf..05968fc8c 100644
--- a/javax/swing/JTextPane.java
+++ b/javax/swing/JTextPane.java
@@ -214,20 +214,11 @@ public class JTextPane
*/
public void insertIcon(Icon icon)
{
- SimpleAttributeSet atts = new SimpleAttributeSet();
- atts.addAttribute(StyleConstants.IconAttribute, icon);
- atts.addAttribute(StyleConstants.NameAttribute,
- StyleConstants.IconElementName);
- try
- {
- getDocument().insertString(getCaret().getDot(), " ", atts);
- }
- catch (BadLocationException ex)
- {
- AssertionError err = new AssertionError("Unexpected bad location");
- err.initCause(ex);
- throw err;
- }
+ MutableAttributeSet inputAtts = getInputAttributes();
+ inputAtts.removeAttributes(inputAtts);
+ StyleConstants.setIcon(inputAtts, icon);
+ replaceSelection(" ");
+ inputAtts.removeAttributes(inputAtts);
}
/**
diff --git a/javax/swing/JTree.java b/javax/swing/JTree.java
index 6530265b9..7d9a22fb9 100644
--- a/javax/swing/JTree.java
+++ b/javax/swing/JTree.java
@@ -1509,12 +1509,14 @@ public class JTree extends JComponent implements Scrollable, Accessible
public JTree(TreeModel model)
{
setRootVisible(true);
- setSelectionModel(new EmptySelectionModel());
- selectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+ setSelectionModel( new DefaultTreeSelectionModel() );
// The root node appears expanded by default.
nodeStates = new Hashtable();
+ // The cell renderer gets set by the UI.
+ cellRenderer = null;
+
// Install the UI before installing the model. This way we avoid double
// initialization of lots of UI and model stuff inside the UI and related
// classes. The necessary UI updates are performed via property change
@@ -1682,29 +1684,52 @@ public class JTree extends JComponent implements Scrollable, Accessible
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
int direction)
{
- int delta;
+ int delta = 0;
// Round so that the top would start from the row boundary
if (orientation == SwingConstants.VERTICAL)
{
- // One pixel down, otherwise picks another row too high.
- int row = getClosestRowForLocation(visibleRect.x, visibleRect.y + 1);
- row = row + direction;
- if (row < 0)
- row = 0;
-
- Rectangle newTop = getRowBounds(row);
- delta = newTop.y - visibleRect.y;
+ int row = getClosestRowForLocation(0, visibleRect.y);
+ if (row != -1)
+ {
+ Rectangle b = getRowBounds(row);
+ if (b.y != visibleRect.y)
+ {
+ if (direction < 0)
+ delta = Math.max(0, visibleRect.y - b.y);
+ else
+ delta = b.y + b.height - visibleRect.height;
+ }
+ else
+ {
+ if (direction < 0)
+ {
+ if (row != 0)
+ {
+ b = getRowBounds(row - 1);
+ delta = b.height;
+ }
+ }
+ else
+ delta = b.height;
+ }
+ }
}
else
- delta = direction * rowHeight == 0 ? 20 : rowHeight;
+ // The RI always returns 4 for HORIZONTAL scrolling.
+ delta = 4;
return delta;
}
public int getScrollableBlockIncrement(Rectangle visibleRect,
int orientation, int direction)
{
- return getScrollableUnitIncrement(visibleRect, orientation, direction);
+ int block;
+ if (orientation == SwingConstants.VERTICAL)
+ block = visibleRect.height;
+ else
+ block = visibleRect.width;
+ return block;
}
public boolean getScrollableTracksViewportHeight()
@@ -2047,14 +2072,16 @@ public class JTree extends JComponent implements Scrollable, Accessible
if (selectionModel == model)
return;
+ if( model == null )
+ model = EmptySelectionModel.sharedInstance();
+
if (selectionModel != null)
selectionModel.removeTreeSelectionListener(selectionRedirector);
TreeSelectionModel oldValue = selectionModel;
selectionModel = model;
- if (selectionModel != null)
- selectionModel.addTreeSelectionListener(selectionRedirector);
+ selectionModel.addTreeSelectionListener(selectionRedirector);
firePropertyChange(SELECTION_MODEL_PROPERTY, oldValue, model);
revalidate();
diff --git a/javax/swing/Popup.java b/javax/swing/Popup.java
index 308cd662d..5074d6418 100644
--- a/javax/swing/Popup.java
+++ b/javax/swing/Popup.java
@@ -284,7 +284,7 @@ public class Popup
panel.setSize(contents.getSize());
Point layeredPaneLoc = layeredPane.getLocationOnScreen();
panel.setLocation(x - layeredPaneLoc.x, y - layeredPaneLoc.y);
- layeredPane.add(panel, JLayeredPane.POPUP_LAYER);
+ layeredPane.add(panel, JLayeredPane.POPUP_LAYER, 0);
panel.repaint();
}
diff --git a/javax/swing/RepaintManager.java b/javax/swing/RepaintManager.java
index 7755ab5e8..80f0a3481 100644
--- a/javax/swing/RepaintManager.java
+++ b/javax/swing/RepaintManager.java
@@ -38,7 +38,6 @@ exception statement from your version. */
package javax.swing;
-import java.applet.Applet;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
@@ -463,8 +462,7 @@ public class RepaintManager
*/
public void markCompletelyDirty(JComponent component)
{
- Rectangle r = component.getBounds();
- addDirtyRegion(component, 0, 0, r.width, r.height);
+ addDirtyRegion(component, 0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
}
/**
@@ -502,13 +500,11 @@ public class RepaintManager
*/
public boolean isCompletelyDirty(JComponent component)
{
- boolean retVal = false;
- if (dirtyComponents.containsKey(component))
- {
- Rectangle dirtyRegion = (Rectangle) dirtyComponents.get(component);
- retVal = dirtyRegion.equals(SwingUtilities.getLocalBounds(component));
- }
- return retVal;
+ boolean dirty = false;
+ Rectangle r = getDirtyRegion(component);
+ if(r.width == Integer.MAX_VALUE && r.height == Integer.MAX_VALUE)
+ dirty = true;
+ return dirty;
}
/**
@@ -647,7 +643,7 @@ public class RepaintManager
width = Math.min(doubleBufferMaximumSize.width, width);
int height = Math.max(proposedHeight, root.getHeight());
height = Math.min(doubleBufferMaximumSize.height, height);
- buffer = component.createImage(width, height);
+ buffer = root.createImage(width, height);
offscreenBuffers.put(root, buffer);
}
return buffer;
diff --git a/javax/swing/SwingUtilities.java b/javax/swing/SwingUtilities.java
index d7808ba60..ba4c708fb 100644
--- a/javax/swing/SwingUtilities.java
+++ b/javax/swing/SwingUtilities.java
@@ -61,6 +61,8 @@ import javax.accessibility.Accessible;
import javax.accessibility.AccessibleStateSet;
import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.InputMapUIResource;
+import javax.swing.plaf.basic.BasicHTML;
+import javax.swing.text.View;
/**
* A number of static utility functions which are
@@ -751,12 +753,12 @@ public class SwingUtilities
horizontalAlignment = RIGHT;
}
- return layoutCompoundLabel(fm, text, icon,
- verticalAlignment,
- horizontalAlignment,
- verticalTextPosition,
- horizontalTextPosition,
- viewR, iconR, textR, textIconGap);
+ return layoutCompoundLabelImpl(c, fm, text, icon,
+ verticalAlignment,
+ horizontalAlignment,
+ verticalTextPosition,
+ horizontalTextPosition,
+ viewR, iconR, textR, textIconGap);
}
/**
@@ -829,6 +831,82 @@ public class SwingUtilities
Rectangle textR,
int textIconGap)
{
+ return layoutCompoundLabelImpl(null, fm, text, icon, verticalAlignment,
+ horizontalAlignment, verticalTextPosition,
+ horizontalTextPosition, viewR, iconR, textR,
+ textIconGap);
+ }
+
+ /**
+ * <p>Layout a "compound label" consisting of a text string and an icon
+ * which is to be placed near the rendered text. Once the text and icon
+ * are laid out, the text rectangle and icon rectangle parameters are
+ * altered to store the calculated positions.</p>
+ *
+ * <p>The size of the text is calculated from the provided font metrics
+ * object. This object should be the metrics of the font you intend to
+ * paint the label with.</p>
+ *
+ * <p>The position values control where the text is placed relative to
+ * the icon. The horizontal position value should be one of the constants
+ * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>. The
+ * vertical position value should be one fo the constants
+ * <code>TOP</code>, <code>BOTTOM</code> or <code>CENTER</code>.</p>
+ *
+ * <p>The text-icon gap value controls the number of pixels between the
+ * icon and the text.</p>
+ *
+ * <p>The alignment values control where the text and icon are placed, as
+ * a combined unit, within the view rectangle. The horizontal alignment
+ * value should be one of the constants <code>LEFT</code>, <code>RIGHT</code> or
+ * <code>CENTER</code>. The vertical alignment valus should be one of the
+ * constants <code>TOP</code>, <code>BOTTOM</code> or
+ * <code>CENTER</code>.</p>
+ *
+ * <p>If the text and icon are equal to or larger than the view
+ * rectangle, the horizontal and vertical alignment values have no
+ * affect.</p>
+ *
+ * <p>Note that this method does <em>not</em> know how to deal with
+ * horizontal alignments or positions given as <code>LEADING</code> or
+ * <code>TRAILING</code> values. Use the other overloaded variant of this
+ * method if you wish to use such values.
+ *
+ * @param fm The font metrics used to measure the text
+ * @param text The text to place in the compound label
+ * @param icon The icon to place next to the text
+ * @param verticalAlignment The vertical alignment of the label relative
+ * to its component
+ * @param horizontalAlignment The horizontal alignment of the label
+ * relative to its component
+ * @param verticalTextPosition The vertical position of the label's text
+ * relative to its icon
+ * @param horizontalTextPosition The horizontal position of the label's
+ * text relative to its icon
+ * @param viewR The view rectangle, specifying the area which layout is
+ * constrained to
+ * @param iconR A rectangle which is modified to hold the laid-out
+ * position of the icon
+ * @param textR A rectangle which is modified to hold the laid-out
+ * position of the text
+ * @param textIconGap The distance between text and icon
+ *
+ * @return The string of characters, possibly truncated with an elipsis,
+ * which is laid out in this label
+ */
+ private static String layoutCompoundLabelImpl(JComponent c,
+ FontMetrics fm,
+ String text,
+ Icon icon,
+ int verticalAlignment,
+ int horizontalAlignment,
+ int verticalTextPosition,
+ int horizontalTextPosition,
+ Rectangle viewR,
+ Rectangle iconR,
+ Rectangle textR,
+ int textIconGap)
+ {
// Work out basic height and width.
@@ -851,13 +929,23 @@ public class SwingUtilities
}
else
{
- int fromIndex = 0;
- textR.width = fm.stringWidth(text);
- textR.height = fm.getHeight();
- while (text.indexOf('\n', fromIndex) != -1)
+ View html = c == null ? null
+ : (View) c.getClientProperty(BasicHTML.propertyKey);
+ if (html != null)
+ {
+ textR.width = (int) html.getPreferredSpan(View.X_AXIS);
+ textR.height = (int) html.getPreferredSpan(View.Y_AXIS);
+ }
+ else
{
- textR.height += fm.getHeight();
- fromIndex = text.indexOf('\n', fromIndex) + 1;
+ int fromIndex = 0;
+ textR.width = fm.stringWidth(text);
+ textR.height = fm.getHeight();
+ while (text.indexOf('\n', fromIndex) != -1)
+ {
+ textR.height += fm.getHeight();
+ fromIndex = text.indexOf('\n', fromIndex) + 1;
+ }
}
}
@@ -1045,8 +1133,7 @@ public class SwingUtilities
*/
public static boolean isLeftMouseButton(MouseEvent event)
{
- return ((event.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK)
- == InputEvent.BUTTON1_DOWN_MASK);
+ return ((event.getModifiers() & InputEvent.BUTTON1_MASK) != 0);
}
/**
diff --git a/javax/swing/Timer.java b/javax/swing/Timer.java
index 231b71d73..acd226249 100644
--- a/javax/swing/Timer.java
+++ b/javax/swing/Timer.java
@@ -1,5 +1,5 @@
/* Timer.java --
- Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -264,9 +264,13 @@ public class Timer
* firing the first event.
*
* @param d The time gap between the subsequent events, in milliseconds
+ *
+ * @throws IllegalArgumentException if <code>d</code> is less than zero.
*/
public void setDelay(int d)
{
+ if (d < 0)
+ throw new IllegalArgumentException("Invalid delay: " + d);
delay = d;
}
@@ -287,9 +291,13 @@ public class Timer
* subsequent events.
*
* @param i the initial delay, in milliseconds
+ *
+ * @throws IllegalArgumentException if <code>i</code> is less than zero.
*/
public void setInitialDelay(int i)
{
+ if (i < 0)
+ throw new IllegalArgumentException("Invalid initial delay: " + i);
initialDelay = i;
}
diff --git a/javax/swing/ToolTipManager.java b/javax/swing/ToolTipManager.java
index c7de4db83..963ccf881 100644
--- a/javax/swing/ToolTipManager.java
+++ b/javax/swing/ToolTipManager.java
@@ -1,5 +1,5 @@
/* ToolTipManager.java --
- Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -267,10 +267,12 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
}
/**
- * This method sets the initial delay before the ToolTip is shown when the
+ * Sets the initial delay before the ToolTip is shown when the
* mouse enters a Component.
*
* @param delay The initial delay before the ToolTip is shown.
+ *
+ * @throws IllegalArgumentException if <code>delay</code> is less than zero.
*/
public void setInitialDelay(int delay)
{
@@ -289,9 +291,11 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
}
/**
- * This method sets the time the ToolTip will be shown before being hidden.
+ * Sets the time the ToolTip will be shown before being hidden.
*
- * @param delay The time the ToolTip will be shown before being hidden.
+ * @param delay the delay (in milliseconds) before tool tips are hidden.
+ *
+ * @throws IllegalArgumentException if <code>delay</code> is less than zero.
*/
public void setDismissDelay(int delay)
{
@@ -310,10 +314,12 @@ public class ToolTipManager extends MouseAdapter implements MouseMotionListener
}
/**
- * This method sets the amount of delay where if the mouse re-enters a
+ * Sets the amount of delay where if the mouse re-enters a
* Component, the tooltip will be shown immediately.
*
- * @param delay The reshow delay.
+ * @param delay The reshow delay (in milliseconds).
+ *
+ * @throws IllegalArgumentException if <code>delay</code> is less than zero.
*/
public void setReshowDelay(int delay)
{
diff --git a/javax/swing/UIManager.java b/javax/swing/UIManager.java
index b70d13952..77be44afc 100644
--- a/javax/swing/UIManager.java
+++ b/javax/swing/UIManager.java
@@ -616,7 +616,7 @@ public class UIManager implements Serializable
*/
public static UIDefaults getLookAndFeelDefaults()
{
- return currentUIDefaults;
+ return lookAndFeelDefaults;
}
/**
@@ -714,7 +714,8 @@ public class UIManager implements Serializable
throws UnsupportedLookAndFeelException
{
if (newLookAndFeel != null && ! newLookAndFeel.isSupportedLookAndFeel())
- throw new UnsupportedLookAndFeelException(newLookAndFeel.getName());
+ throw new UnsupportedLookAndFeelException(newLookAndFeel.getName()
+ + " not supported on this platform");
LookAndFeel oldLookAndFeel = currentLookAndFeel;
if (oldLookAndFeel != null)
oldLookAndFeel.uninitialize();
diff --git a/javax/swing/filechooser/FileSystemView.java b/javax/swing/filechooser/FileSystemView.java
index f51b745c8..84b80dd40 100644
--- a/javax/swing/filechooser/FileSystemView.java
+++ b/javax/swing/filechooser/FileSystemView.java
@@ -76,7 +76,10 @@ public abstract class FileSystemView
*/
public File createFileObject(String path)
{
- return new File(path);
+ File f = new File(path);
+ if (isFileSystemRoot(f))
+ f = this.createFileSystemRoot(f);
+ return f;
}
/**
@@ -223,16 +226,24 @@ public abstract class FileSystemView
/**
* Returns the name of a file as it would be displayed by the underlying
- * system. This implementation returns <code>null</code>, subclasses must
- * override.
+ * system.
*
* @param f the file.
*
- * @return <code>null</code>.
+ * @return the name of a file as it would be displayed by the underlying
+ * system
+ *
+ * @specnote The specification suggests that the information here is
+ * fetched from a ShellFolder class. This seems to be a non public
+ * private file handling class. We simply return File.getName()
+ * here and leave special handling to subclasses.
*/
public String getSystemDisplayName(File f)
{
- return null;
+ String name = null;
+ if (f != null)
+ name = f.getName();
+ return name;
}
/**
diff --git a/javax/swing/filechooser/UnixFileSystemView.java b/javax/swing/filechooser/UnixFileSystemView.java
index 96dfd2e1b..f8d71e1df 100644
--- a/javax/swing/filechooser/UnixFileSystemView.java
+++ b/javax/swing/filechooser/UnixFileSystemView.java
@@ -106,17 +106,34 @@ class UnixFileSystemView extends FileSystemView
/**
* Returns the name of a file as it would be displayed by the underlying
- * system. This method is NOT YET IMPLEMENTED.
+ * system.
*
* @param f the file.
*
- * @return <code>null</code>.
+ * @return the name of a file as it would be displayed by the underlying
+ * system
*/
public String getSystemDisplayName(File f)
- throws NotImplementedException
{
- // FIXME: Implement;
- return null;
+ String name = null;
+ if (f != null)
+ {
+ if (isRoot(f))
+ name = f.getAbsolutePath();
+ else
+ {
+ try
+ {
+ String path = f.getCanonicalPath();
+ name = path.substring(path.lastIndexOf(File.separator) + 1);
+ }
+ catch (IOException e)
+ {
+ name = f.getName();
+ }
+ }
+ }
+ return name;
}
/**
diff --git a/javax/swing/plaf/basic/BasicButtonListener.java b/javax/swing/plaf/basic/BasicButtonListener.java
index fe0365a50..042192b62 100644
--- a/javax/swing/plaf/basic/BasicButtonListener.java
+++ b/javax/swing/plaf/basic/BasicButtonListener.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package javax.swing.plaf.basic;
+import gnu.classpath.SystemProperties;
+
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
@@ -71,10 +73,12 @@ public class BasicButtonListener implements MouseListener, MouseMotionListener,
// Store the TextLayout for this in a client property for speed-up
// painting of the label.
String property = e.getPropertyName();
- if (property.equals(AbstractButton.TEXT_CHANGED_PROPERTY)
- || property.equals("font"))
+ AbstractButton b = (AbstractButton) e.getSource();
+ if ((property.equals(AbstractButton.TEXT_CHANGED_PROPERTY)
+ || property.equals("font"))
+ && SystemProperties.getProperty("gnu.javax.swing.noGraphics2D")
+ == null)
{
- AbstractButton b = (AbstractButton) e.getSource();
String text = b.getText();
if (text == null)
text = "";
@@ -83,6 +87,10 @@ public class BasicButtonListener implements MouseListener, MouseMotionListener,
TextLayout layout = new TextLayout(text, b.getFont(), frc);
b.putClientProperty(BasicGraphicsUtils.CACHED_TEXT_LAYOUT, layout);
}
+ if (property.equals(AbstractButton.TEXT_CHANGED_PROPERTY))
+ {
+ BasicHTML.updateRenderer(b, b.getText());
+ }
}
protected void checkOpacity(AbstractButton b)
@@ -176,11 +184,14 @@ public class BasicButtonListener implements MouseListener, MouseMotionListener,
{
AbstractButton button = (AbstractButton) e.getSource();
ButtonModel model = button.getModel();
- if (e.getButton() == MouseEvent.BUTTON1)
+ if (SwingUtilities.isLeftMouseButton(e))
{
// It is important that these transitions happen in this order.
model.setArmed(true);
model.setPressed(true);
+
+ if (! button.isFocusOwner() && button.isRequestFocusEnabled())
+ button.requestFocus();
}
}
}
diff --git a/javax/swing/plaf/basic/BasicButtonUI.java b/javax/swing/plaf/basic/BasicButtonUI.java
index d531133ba..cdaec2543 100644
--- a/javax/swing/plaf/basic/BasicButtonUI.java
+++ b/javax/swing/plaf/basic/BasicButtonUI.java
@@ -56,6 +56,7 @@ import javax.swing.UIManager;
import javax.swing.plaf.ButtonUI;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
+import javax.swing.text.View;
/**
* A UI delegate for the {@link JButton} component.
@@ -255,10 +256,72 @@ public class BasicButtonUI extends ButtonUI
installDefaults(b);
installListeners(b);
installKeyboardActions(b);
+ BasicHTML.updateRenderer(b, b.getText());
}
}
/**
+ * Uninstalls the UI from the component.
+ *
+ * @param c the component from which to uninstall the UI
+ */
+ public void uninstallUI(JComponent c)
+ {
+ if (c instanceof AbstractButton)
+ {
+ AbstractButton b = (AbstractButton) c;
+ uninstallKeyboardActions(b);
+ uninstallListeners(b);
+ uninstallDefaults(b);
+ BasicHTML.updateRenderer(b, "");
+ }
+ }
+
+ /**
+ * Calculates the minimum size for the specified component.
+ *
+ * @param c the component for which to compute the minimum size
+ *
+ * @return the minimum size for the specified component
+ */
+ public Dimension getMinimumSize(JComponent c)
+ {
+ Dimension size = getPreferredSize(c);
+ // When the HTML view has a minimum width different from the preferred
+ // width, then substract this here accordingly. The height is not
+ // affected by that.
+ View html = (View) c.getClientProperty(BasicHTML.propertyKey);
+ if (html != null)
+ {
+ size.width -= html.getPreferredSpan(View.X_AXIS)
+ - html.getPreferredSpan(View.X_AXIS);
+ }
+ return size;
+ }
+
+ /**
+ * Calculates the maximum size for the specified component.
+ *
+ * @param c the component for which to compute the maximum size
+ *
+ * @return the maximum size for the specified component
+ */
+ public Dimension getMaximumSize(JComponent c)
+ {
+ Dimension size = getPreferredSize(c);
+ // When the HTML view has a maximum width different from the preferred
+ // width, then add this here accordingly. The height is not
+ // affected by that.
+ View html = (View) c.getClientProperty(BasicHTML.propertyKey);
+ if (html != null)
+ {
+ size.width += html.getMaximumSpan(View.X_AXIS)
+ - html.getPreferredSpan(View.X_AXIS);
+ }
+ return size;
+ }
+
+ /**
* Calculate the preferred size of this component, by delegating to
* {@link BasicGraphicsUtils#getPreferredButtonSize}.
*
@@ -269,8 +332,8 @@ public class BasicButtonUI extends ButtonUI
public Dimension getPreferredSize(JComponent c)
{
AbstractButton b = (AbstractButton) c;
- Dimension d = BasicGraphicsUtils.getPreferredButtonSize(b,
- defaultTextIconGap + defaultTextShiftOffset);
+ Dimension d = BasicGraphicsUtils.getPreferredButtonSize(b,
+ b.getIconTextGap());
return d;
}
@@ -344,7 +407,13 @@ public class BasicButtonUI extends ButtonUI
paintIcon(g, c, ir);
if (text != null)
- paintText(g, b, tr, text);
+ {
+ View html = (View) b.getClientProperty(BasicHTML.propertyKey);
+ if (html != null)
+ html.paint(g, tr);
+ else
+ paintText(g, b, tr, text);
+ }
if (b.isFocusOwner() && b.isFocusPainted())
paintFocus(g, b, vr, tr, ir);
}
diff --git a/javax/swing/plaf/basic/BasicComboBoxUI.java b/javax/swing/plaf/basic/BasicComboBoxUI.java
index ea97782c3..d98fd2afe 100644
--- a/javax/swing/plaf/basic/BasicComboBoxUI.java
+++ b/javax/swing/plaf/basic/BasicComboBoxUI.java
@@ -289,7 +289,7 @@ public class BasicComboBoxUI extends ComboBoxUI
comboBox.addPropertyChangeListener(propertyChangeListener);
focusListener = createFocusListener();
- editor.addFocusListener(focusListener);
+ comboBox.addFocusListener(focusListener);
itemListener = createItemListener();
comboBox.addItemListener(itemListener);
@@ -543,7 +543,9 @@ public class BasicComboBoxUI extends ComboBoxUI
{
editor.setFont(comboBox.getFont());
if (popupKeyListener != null)
- editor.addKeyListener(popupKeyListener);
+ editor.addKeyListener(popupKeyListener);
+ if (keyListener != null)
+ editor.addKeyListener(keyListener);
comboBox.configureEditor(comboBox.getEditor(),
comboBox.getSelectedItem());
}
@@ -555,6 +557,8 @@ public class BasicComboBoxUI extends ComboBoxUI
{
if (popupKeyListener != null)
editor.removeKeyListener(popupKeyListener);
+ if (keyListener != null)
+ editor.removeKeyListener(keyListener);
}
/**
@@ -775,7 +779,9 @@ public class BasicComboBoxUI extends ComboBoxUI
protected boolean isNavigationKey(int keyCode)
{
return keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_DOWN
- || keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT;
+ || keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT
+ || keyCode == KeyEvent.VK_ENTER || keyCode == KeyEvent.VK_ESCAPE
+ || keyCode == KeyEvent.VK_TAB;
}
/**
@@ -796,7 +802,7 @@ public class BasicComboBoxUI extends ComboBoxUI
protected void selectPreviousPossibleValue()
{
int index = comboBox.getSelectedIndex();
- if (index != 0)
+ if (index > 0)
comboBox.setSelectedIndex(index - 1);
}
@@ -1201,11 +1207,29 @@ public class BasicComboBoxUI extends ComboBoxUI
*/
public void keyPressed(KeyEvent e)
{
- if (! isNavigationKey(e.getKeyCode()) && comboBox.isEnabled()
- && comboBox.getModel().getSize() != 0)
+ if (comboBox.getModel().getSize() != 0 && comboBox.isEnabled())
{
- if (comboBox.selectWithKeyChar(e.getKeyChar()))
- e.consume();
+ if (! isNavigationKey(e.getKeyCode()))
+ {
+ if (! comboBox.isEditable())
+ if (comboBox.selectWithKeyChar(e.getKeyChar()))
+ e.consume();
+ }
+ else
+ {
+ if (e.getKeyCode() == KeyEvent.VK_UP && comboBox.isPopupVisible())
+ selectPreviousPossibleValue();
+ else if (e.getKeyCode() == KeyEvent.VK_DOWN)
+ {
+ if (comboBox.isPopupVisible())
+ selectNextPossibleValue();
+ else
+ comboBox.showPopup();
+ }
+ else if (e.getKeyCode() == KeyEvent.VK_ENTER
+ || e.getKeyCode() == KeyEvent.VK_ESCAPE)
+ popup.hide();
+ }
}
}
}
@@ -1370,5 +1394,4 @@ public class BasicComboBoxUI extends ComboBoxUI
// FIXME: Need to handle changes in other bound properties.
}
}
-
}
diff --git a/javax/swing/plaf/basic/BasicDirectoryModel.java b/javax/swing/plaf/basic/BasicDirectoryModel.java
index ef7a880c2..ed916cb5f 100644
--- a/javax/swing/plaf/basic/BasicDirectoryModel.java
+++ b/javax/swing/plaf/basic/BasicDirectoryModel.java
@@ -1,5 +1,5 @@
/* BasicDirectoryModel.java --
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -40,35 +40,296 @@ package javax.swing.plaf.basic;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
import java.util.Vector;
import javax.swing.AbstractListModel;
import javax.swing.JFileChooser;
+import javax.swing.SwingUtilities;
import javax.swing.event.ListDataEvent;
import javax.swing.filechooser.FileSystemView;
/**
- * DOCUMENT ME!
+ * Implements an AbstractListModel for directories where the source
+ * of the files is a JFileChooser object.
+ *
+ * This class is used for sorting and ordering the file list in
+ * a JFileChooser L&F object.
*/
public class BasicDirectoryModel extends AbstractListModel
implements PropertyChangeListener
{
- /** DOCUMENT ME! */
+ /** The list of files itself */
private Vector contents;
- /** DOCUMENT ME! */
- private int directories;
+ /**
+ * The directories in the list.
+ */
+ private Vector directories;
+
+ /**
+ * The files in the list.
+ */
+ private Vector files;
- /** DOCUMENT ME! */
+ /** The listing mode of the associated JFileChooser,
+ either FILES_ONLY, DIRECTORIES_ONLY or FILES_AND_DIRECTORIES */
private int listingMode;
- /** DOCUMENT ME! */
+ /** The JFileCooser associated with this model */
private JFileChooser filechooser;
- /** DOCUMENT ME! */
+ /**
+ * The thread that loads the file view.
+ */
+ private DirectoryLoadThread loadThread;
+
+ /**
+ * This thread is responsible for loading file lists from the
+ * current directory and updating the model.
+ */
+ private class DirectoryLoadThread extends Thread
+ {
+
+ /**
+ * Updates the Swing list model.
+ */
+ private class UpdateSwingRequest
+ implements Runnable
+ {
+
+ private List added;
+ private int addIndex;
+ private List removed;
+ private int removeIndex;
+ private boolean cancel;
+
+ UpdateSwingRequest(List add, int ai, List rem, int ri)
+ {
+ added = add;
+ addIndex = ai;
+ removed = rem;
+ removeIndex = ri;
+ cancel = false;
+ }
+
+ public void run()
+ {
+ if (! cancel)
+ {
+ int numRemoved = removed == null ? 0 : removed.size();
+ int numAdded = added == null ? 0 : added.size();
+ synchronized (contents)
+ {
+ if (numRemoved > 0)
+ contents.removeAll(removed);
+ if (numAdded > 0)
+ contents.addAll(added);
+
+ files = null;
+ directories = null;
+ }
+ if (numRemoved > 0 && numAdded == 0)
+ fireIntervalRemoved(BasicDirectoryModel.this, removeIndex,
+ removeIndex + numRemoved - 1);
+ else if (numRemoved == 0 && numAdded > 0)
+ fireIntervalAdded(BasicDirectoryModel.this, addIndex,
+ addIndex + numAdded - 1);
+ else
+ fireContentsChanged();
+ }
+ }
+
+ void cancel()
+ {
+ cancel = true;
+ }
+ }
+
+ /**
+ * The directory beeing loaded.
+ */
+ File directory;
+
+ /**
+ * Stores all UpdateSwingRequests that are sent to the event queue.
+ */
+ private UpdateSwingRequest pending;
+
+ /**
+ * Creates a new DirectoryLoadThread that loads the specified
+ * directory.
+ *
+ * @param dir the directory to load
+ */
+ DirectoryLoadThread(File dir)
+ {
+ super("Basic L&F directory loader");
+ directory = dir;
+ }
+
+ public void run()
+ {
+ FileSystemView fsv = filechooser.getFileSystemView();
+ File[] files = fsv.getFiles(directory,
+ filechooser.isFileHidingEnabled());
+
+ // Occasional check if we have been interrupted.
+ if (isInterrupted())
+ return;
+
+ // Check list for accepted files.
+ Vector accepted = new Vector();
+ for (int i = 0; i < files.length; i++)
+ {
+ if (filechooser.accept(files[i]))
+ accepted.add(files[i]);
+ }
+
+ // Occasional check if we have been interrupted.
+ if (isInterrupted())
+ return;
+
+ // Sort list.
+ sort(accepted);
+
+ // Now split up directories from files so that we get the directories
+ // listed before the files.
+ Vector newFiles = new Vector();
+ Vector newDirectories = new Vector();
+ for (Iterator i = accepted.iterator(); i.hasNext();)
+ {
+ File f = (File) i.next();
+ boolean traversable = filechooser.isTraversable(f);
+ if (traversable)
+ newDirectories.add(f);
+ else if (! traversable && filechooser.isFileSelectionEnabled())
+ newFiles.add(f);
+
+ // Occasional check if we have been interrupted.
+ if (isInterrupted())
+ return;
+
+ }
+
+ // Build up new file cache. Try to update only the changed elements.
+ // This will be important for actions like adding new files or
+ // directories inside a large file list.
+ Vector newCache = new Vector(newDirectories);
+ newCache.addAll(newFiles);
+
+ int newSize = newCache.size();
+ int oldSize = contents.size();
+ if (newSize < oldSize)
+ {
+ // Check for removed interval.
+ int start = -1;
+ int end = -1;
+ boolean found = false;
+ for (int i = 0; i < newSize && !found; i++)
+ {
+ if (! newCache.get(i).equals(contents.get(i)))
+ {
+ start = i;
+ end = i + oldSize - newSize;
+ found = true;
+ }
+ }
+ if (start >= 0 && end > start
+ && contents.subList(end, oldSize)
+ .equals(newCache.subList(start, newSize)))
+ {
+ // Occasional check if we have been interrupted.
+ if (isInterrupted())
+ return;
+
+ Vector removed = new Vector(contents.subList(start, end));
+ UpdateSwingRequest r = new UpdateSwingRequest(null, 0,
+ removed, start);
+ invokeLater(r);
+ newCache = null;
+ }
+ }
+ else if (newSize > oldSize)
+ {
+ // Check for inserted interval.
+ int start = oldSize;
+ int end = newSize;
+ boolean found = false;
+ for (int i = 0; i < oldSize && ! found; i++)
+ {
+ if (! newCache.get(i).equals(contents.get(i)))
+ {
+ start = i;
+ boolean foundEnd = false;
+ for (int j = i; j < newSize && ! foundEnd; j++)
+ {
+ if (newCache.get(j).equals(contents.get(i)))
+ {
+ end = j;
+ foundEnd = true;
+ }
+ }
+ end = i + oldSize - newSize;
+ }
+ }
+ if (start >= 0 && end > start
+ && newCache.subList(end, newSize)
+ .equals(contents.subList(start, oldSize)))
+ {
+ // Occasional check if we have been interrupted.
+ if (isInterrupted())
+ return;
+
+ List added = newCache.subList(start, end);
+ UpdateSwingRequest r = new UpdateSwingRequest(added, start,
+ null, 0);
+ invokeLater(r);
+ newCache = null;
+ }
+ }
+
+ // Handle complete list changes (newCache != null).
+ if (newCache != null && ! contents.equals(newCache))
+ {
+ // Occasional check if we have been interrupted.
+ if (isInterrupted())
+ return;
+ UpdateSwingRequest r = new UpdateSwingRequest(newCache, 0,
+ contents, 0);
+ invokeLater(r);
+ }
+ }
+
+ /**
+ * Wraps SwingUtilities.invokeLater() and stores the request in
+ * a Vector so that we can still cancel it later.
+ *
+ * @param update the request to invoke
+ */
+ private void invokeLater(UpdateSwingRequest update)
+ {
+ pending = update;
+ SwingUtilities.invokeLater(update);
+ }
+
+ /**
+ * Cancels all pending update requests that might be in the AWT
+ * event queue.
+ */
+ void cancelPending()
+ {
+ if (pending != null)
+ pending.cancel();
+ }
+ }
+
+ /** A Comparator class/object for sorting the file list. */
private Comparator comparator = new Comparator()
{
public int compare(Object o1, Object o2)
@@ -91,14 +352,15 @@ public class BasicDirectoryModel extends AbstractListModel
filechooser.addPropertyChangeListener(this);
listingMode = filechooser.getFileSelectionMode();
contents = new Vector();
+ validateFileCache();
}
/**
- * DOCUMENT ME!
+ * Returns whether a given (File) object is included in the list.
*
- * @param o DOCUMENT ME!
+ * @param o - The file object to test.
*
- * @return DOCUMENT ME!
+ * @return <code>true</code> if the list contains the given object.
*/
public boolean contains(Object o)
{
@@ -106,7 +368,7 @@ public class BasicDirectoryModel extends AbstractListModel
}
/**
- * DOCUMENT ME!
+ * Fires a content change event.
*/
public void fireContentsChanged()
{
@@ -114,80 +376,99 @@ public class BasicDirectoryModel extends AbstractListModel
}
/**
- * DOCUMENT ME!
+ * Returns a Vector of (java.io.File) objects containing
+ * the directories in this list.
*
- * @return DOCUMENT ME!
+ * @return a Vector
*/
public Vector getDirectories()
{
- Vector tmp = new Vector();
- for (int i = 0; i < directories; i++)
- tmp.add(contents.get(i));
- return tmp;
+ // Synchronize this with the UpdateSwingRequest for the case when
+ // contents is modified.
+ synchronized (contents)
+ {
+ Vector dirs = directories;
+ if (dirs == null)
+ {
+ // Initializes this in getFiles().
+ getFiles();
+ dirs = directories;
+ }
+ return dirs;
+ }
}
/**
- * DOCUMENT ME!
+ * Returns the (java.io.File) object at
+ * an index in the list.
*
- * @param index DOCUMENT ME!
- *
- * @return DOCUMENT ME!
+ * @param index The list index
+ * @return a File object
*/
public Object getElementAt(int index)
{
if (index > getSize() - 1)
return null;
- if (listingMode == JFileChooser.FILES_ONLY)
- return contents.get(directories + index);
- else
- return contents.elementAt(index);
+ return contents.elementAt(index);
}
/**
- * DOCUMENT ME!
+ * Returns a Vector of (java.io.File) objects containing
+ * the files in this list.
*
- * @return DOCUMENT ME!
+ * @return a Vector
*/
public Vector getFiles()
{
- Vector tmp = new Vector();
- for (int i = directories; i < getSize(); i++)
- tmp.add(contents.get(i));
- return tmp;
+ synchronized (contents)
+ {
+ Vector f = files;
+ if (f == null)
+ {
+ f = new Vector();
+ Vector d = new Vector(); // Directories;
+ for (Iterator i = contents.iterator(); i.hasNext();)
+ {
+ File file = (File) i.next();
+ if (filechooser.isTraversable(file))
+ d.add(file);
+ else
+ f.add(file);
+ }
+ files = f;
+ directories = d;
+ }
+ return f;
+ }
}
/**
- * DOCUMENT ME!
+ * Returns the size of the list, which only includes directories
+ * if the JFileChooser is set to DIRECTORIES_ONLY.
+ *
+ * Otherwise, both directories and files are included in the count.
*
- * @return DOCUMENT ME!
+ * @return The size of the list.
*/
public int getSize()
{
- if (listingMode == JFileChooser.DIRECTORIES_ONLY)
- return directories;
- else if (listingMode == JFileChooser.FILES_ONLY)
- return contents.size() - directories;
return contents.size();
}
/**
- * DOCUMENT ME!
+ * Returns the index of an (java.io.File) object in the list.
*
- * @param o DOCUMENT ME!
+ * @param o The object - normally a File.
*
- * @return DOCUMENT ME!
+ * @return the index of that object, or -1 if it is not in the list.
*/
public int indexOf(Object o)
{
- if (listingMode == JFileChooser.FILES_ONLY)
- return contents.indexOf(o) - directories;
return contents.indexOf(o);
}
/**
- * DOCUMENT ME!
- *
- * @param e DOCUMENT ME!
+ * Obsoleted method which does nothing.
*/
public void intervalAdded(ListDataEvent e)
{
@@ -195,9 +476,7 @@ public class BasicDirectoryModel extends AbstractListModel
}
/**
- * DOCUMENT ME!
- *
- * @param e DOCUMENT ME!
+ * Obsoleted method which does nothing.
*/
public void intervalRemoved(ListDataEvent e)
{
@@ -205,7 +484,7 @@ public class BasicDirectoryModel extends AbstractListModel
}
/**
- * DOCUMENT ME!
+ * Obsoleted method which does nothing.
*/
public void invalidateFileCache()
{
@@ -213,12 +492,16 @@ public class BasicDirectoryModel extends AbstractListModel
}
/**
- * DOCUMENT ME!
+ * Less than, determine the relative order in the list of two files
+ * for sorting purposes.
+ *
+ * The order is: directories < files, and thereafter alphabetically,
+ * using the default locale collation.
*
- * @param a DOCUMENT ME!
- * @param b DOCUMENT ME!
+ * @param a the first file
+ * @param b the second file
*
- * @return DOCUMENT ME!
+ * @return <code>true</code> if a > b, <code>false</code> if a < b.
*/
protected boolean lt(File a, File b)
{
@@ -241,73 +524,66 @@ public class BasicDirectoryModel extends AbstractListModel
}
/**
- * DOCUMENT ME!
+ * Listens for a property change; the change in file selection mode of the
+ * associated JFileChooser. Reloads the file cache on that event.
*
- * @param e DOCUMENT ME!
+ * @param e - A PropertyChangeEvent.
*/
public void propertyChange(PropertyChangeEvent e)
{
- if (e.getPropertyName().equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY))
- listingMode = filechooser.getFileSelectionMode();
+ String property = e.getPropertyName();
+ if (property.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)
+ || property.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)
+ || property.equals(JFileChooser.FILE_HIDING_CHANGED_PROPERTY)
+ || property.equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)
+ || property.equals(JFileChooser.FILE_VIEW_CHANGED_PROPERTY)
+ )
+ {
+ validateFileCache();
+ }
}
/**
- * DOCUMENT ME!
+ * Renames a file - However, does <I>not</I> re-sort the list
+ * or replace the old file with the new one in the list.
*
- * @param oldFile DOCUMENT ME!
- * @param newFile DOCUMENT ME!
+ * @param oldFile The old file
+ * @param newFile The new file name
*
- * @return DOCUMENT ME!
+ * @return <code>true</code> if the rename succeeded
*/
public boolean renameFile(File oldFile, File newFile)
{
- // FIXME: implement
- return false;
+ return oldFile.renameTo( newFile );
}
/**
- * DOCUMENT ME!
+ * Sorts a Vector of File objects.
*
- * @param v DOCUMENT ME!
+ * @param v The Vector to sort.
*/
protected void sort(Vector v)
{
Collections.sort(v, comparator);
- Enumeration e = Collections.enumeration(v);
- Vector tmp = new Vector();
- for (; e.hasMoreElements();)
- tmp.add(e.nextElement());
-
- contents = tmp;
}
/**
- * DOCUMENT ME!
+ * Re-loads the list of files
*/
public void validateFileCache()
{
- contents.clear();
- directories = 0;
- FileSystemView fsv = filechooser.getFileSystemView();
- File[] list = fsv.getFiles(filechooser.getCurrentDirectory(),
- filechooser.isFileHidingEnabled());
-
- if (list == null)
- return;
-
- for (int i = 0; i < list.length; i++)
+ File dir = filechooser.getCurrentDirectory();
+ if (dir != null)
{
- if (list[i] == null)
- continue;
- if (filechooser.accept(list[i]))
- {
- contents.add(list[i]);
- if (filechooser.isTraversable(list[i]))
- directories++;
- }
+ // Cancel all pending requests.
+ if (loadThread != null)
+ {
+ loadThread.interrupt();
+ loadThread.cancelPending();
+ }
+ loadThread = new DirectoryLoadThread(dir);
+ loadThread.start();
}
- sort(contents);
- filechooser.revalidate();
- filechooser.repaint();
}
}
+
diff --git a/javax/swing/plaf/basic/BasicFileChooserUI.java b/javax/swing/plaf/basic/BasicFileChooserUI.java
index 1356db4ae..dc1c05122 100644
--- a/javax/swing/plaf/basic/BasicFileChooserUI.java
+++ b/javax/swing/plaf/basic/BasicFileChooserUI.java
@@ -160,6 +160,8 @@ public class BasicFileChooserUI extends FileChooserUI
else
{
File f = new File(filechooser.getCurrentDirectory(), getFileName());
+ if ( selectedDir != null )
+ f = selectedDir;
if (filechooser.isTraversable(f))
{
filechooser.setCurrentDirectory(f);
@@ -266,7 +268,14 @@ public class BasicFileChooserUI extends FileChooserUI
*/
public String getName(File f)
{
- return f.getName();
+ String name = null;
+ if (f != null)
+ {
+ JFileChooser c = getFileChooser();
+ FileSystemView v = c.getFileSystemView();
+ name = v.getSystemDisplayName(f);
+ }
+ return name;
}
/**
@@ -409,7 +418,7 @@ public class BasicFileChooserUI extends FileChooserUI
closeDialog();
}
}
- else
+ else // single click
{
String path = p.toString();
File f = fsv.createFileObject(path);
@@ -436,10 +445,11 @@ public class BasicFileChooserUI extends FileChooserUI
}
lastSelected = path;
parentPath = path.substring(0, path.lastIndexOf("/") + 1);
+
if (f.isFile())
setFileName(path.substring(path.lastIndexOf("/") + 1));
- else if (filechooser.getFileSelectionMode() ==
- JFileChooser.DIRECTORIES_ONLY)
+ else if (filechooser.getFileSelectionMode() !=
+ JFileChooser.FILES_ONLY)
setFileName(path);
}
}
@@ -538,7 +548,7 @@ public class BasicFileChooserUI extends FileChooserUI
}
/**
- * DOCUMENT ME!
+ * Sets the JFileChooser to the selected file on an update
*
* @param e DOCUMENT ME!
*/
@@ -550,9 +560,15 @@ public class BasicFileChooserUI extends FileChooserUI
return;
File file = filechooser.getFileSystemView().createFileObject(f.toString());
if (! filechooser.isTraversable(file))
- filechooser.setSelectedFile(file);
+ {
+ selectedDir = null;
+ filechooser.setSelectedFile(file);
+ }
else
- filechooser.setSelectedFile(null);
+ {
+ selectedDir = file;
+ filechooser.setSelectedFile(null);
+ }
}
}
@@ -752,6 +768,13 @@ public class BasicFileChooserUI extends FileChooserUI
* @see #getUpdateAction()
*/
private UpdateAction updateAction;
+
+ /**
+ * When in FILES_ONLY, mode a directory cannot be selected, so
+ * we save a reference to any it here. This is used to enter
+ * the directory on "Open" when in that mode.
+ */
+ private File selectedDir;
// -- end private --
@@ -874,7 +897,9 @@ public class BasicFileChooserUI extends FileChooserUI
protected void installListeners(JFileChooser fc)
{
propertyChangeListener = createPropertyChangeListener(filechooser);
- filechooser.addPropertyChangeListener(propertyChangeListener);
+ if (propertyChangeListener != null)
+ filechooser.addPropertyChangeListener(propertyChangeListener);
+ fc.addPropertyChangeListener(getModel());
}
/**
@@ -884,8 +909,12 @@ public class BasicFileChooserUI extends FileChooserUI
*/
protected void uninstallListeners(JFileChooser fc)
{
- filechooser.removePropertyChangeListener(propertyChangeListener);
- propertyChangeListener = null;
+ if (propertyChangeListener != null)
+ {
+ filechooser.removePropertyChangeListener(propertyChangeListener);
+ propertyChangeListener = null;
+ }
+ fc.removePropertyChangeListener(getModel());
}
/**
@@ -1046,12 +1075,8 @@ public class BasicFileChooserUI extends FileChooserUI
*/
public PropertyChangeListener createPropertyChangeListener(JFileChooser fc)
{
- return new PropertyChangeListener()
- {
- public void propertyChange(PropertyChangeEvent e)
- {
- }
- };
+ // The RI returns null here, so do we.
+ return null;
}
/**
diff --git a/javax/swing/plaf/basic/BasicHTML.java b/javax/swing/plaf/basic/BasicHTML.java
index 98c9cb277..67f9c20dc 100644
--- a/javax/swing/plaf/basic/BasicHTML.java
+++ b/javax/swing/plaf/basic/BasicHTML.java
@@ -107,6 +107,7 @@ public class BasicHTML
editorKit = kit;
document = doc;
setView(view);
+ setSize(view.getPreferredSpan(X_AXIS), view.getPreferredSpan(Y_AXIS));
}
/**
@@ -151,6 +152,14 @@ public class BasicHTML
}
/**
+ * Overridden to forward to real view.
+ */
+ public void setSize(float w, float h)
+ {
+ view.setSize(w, h);
+ }
+
+ /**
* Returns the real root view, regardless of the index.
*
* @param index not used here
diff --git a/javax/swing/plaf/basic/BasicInternalFrameUI.java b/javax/swing/plaf/basic/BasicInternalFrameUI.java
index bfd97b913..8161df29f 100644
--- a/javax/swing/plaf/basic/BasicInternalFrameUI.java
+++ b/javax/swing/plaf/basic/BasicInternalFrameUI.java
@@ -38,7 +38,6 @@ exception statement from your version. */
package javax.swing.plaf.basic;
-import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
@@ -460,18 +459,12 @@ public class BasicInternalFrameUI extends InternalFrameUI
{
if (frame.isMaximum())
{
- JDesktopPane pane = (JDesktopPane) e.getSource();
- Insets insets = pane.getInsets();
- Rectangle bounds = pane.getBounds();
-
- frame.setBounds(bounds.x + insets.left, bounds.y + insets.top,
- bounds.width - insets.left - insets.right,
- bounds.height - insets.top - insets.bottom);
- frame.revalidate();
- frame.repaint();
+ Container parent = frame.getParent();
+ Insets i = parent.getInsets();
+ int width = parent.getWidth() - i.left - i.right;
+ int height = parent.getHeight() - i.top - i.bottom;
+ frame.setBounds(0, 0, width, height);
}
-
- // Sun also resizes the icons. but it doesn't seem to do anything.
}
/**
@@ -692,17 +685,12 @@ public class BasicInternalFrameUI extends InternalFrameUI
/** The MouseEvent target. */
private transient Component mouseEventTarget;
- /** The component pressed. */
- private transient Component pressedComponent;
-
- /** The last component entered. */
- private transient Component lastComponentEntered;
-
- /** Used to store/reset lastComponentEntered. */
- private transient Component tempComponent;
+ private Component dragTarget;
- /** The number of presses. */
- private transient int pressCount;
+ /**
+ * Indicates if we are currently in a dragging operation or not.
+ */
+ private boolean isDragging;
/**
* This method is called when the mouse enters the glass pane.
@@ -767,7 +755,10 @@ public class BasicInternalFrameUI extends InternalFrameUI
*/
public void mousePressed(MouseEvent e)
{
- activateFrame(frame);
+ // Experiments show that this seems to call the
+ // borderListener.mousePressed() method to activate the frame.
+ if (borderListener != null)
+ borderListener.mousePressed(e);
handleEvent(e);
}
@@ -783,149 +774,104 @@ public class BasicInternalFrameUI extends InternalFrameUI
}
/**
- * This method acquires a candidate component to dispatch the MouseEvent to.
+ * This is a helper method that dispatches the GlassPane MouseEvents to the
+ * proper component.
*
- * @param me
- * The MouseEvent to acquire a component for.
+ * @param e the mouse event to be dispatched
*/
- private void acquireComponentForMouseEvent(MouseEvent me)
+ private void handleEvent(MouseEvent e)
{
- int x = me.getX();
- int y = me.getY();
-
- // Find the candidate which should receive this event.
- Component parent = frame.getLayeredPane();
- if (parent == null)
- return;
- Component candidate = null;
- Point p = me.getPoint();
- while (candidate == null && parent != null)
- {
- candidate = SwingUtilities.getDeepestComponentAt(parent, p.x, p.y);
- if (candidate == null)
- {
- p = SwingUtilities.convertPoint(parent, p.x, p.y,
- parent.getParent());
- parent = parent.getParent();
- }
- }
-
- // If the only candidate we found was the native container itself,
- // don't dispatch any event at all. We only care about the lightweight
- // children here.
- if (candidate == frame.getContentPane())
- candidate = null;
-
- // If our candidate is new, inform the old target we're leaving.
- if (lastComponentEntered != null && lastComponentEntered.isShowing()
- && lastComponentEntered != candidate)
+ // Find candidate component inside the JInternalFrame.
+ Component target = frame.getLayeredPane().findComponentAt(e.getX(),
+ e.getY());
+
+ // Now search upwards to find a component that actually has
+ // a MouseListener attached.
+ while (target != null
+ && target.getMouseListeners().length == 0
+ && target.getMouseMotionListeners().length == 0
+ && target.getMouseWheelListeners().length == 0)
{
- Point tp = SwingUtilities.convertPoint(frame.getContentPane(), x, y,
- lastComponentEntered);
- MouseEvent exited = new MouseEvent(lastComponentEntered,
- MouseEvent.MOUSE_EXITED,
- me.getWhen(), me.getModifiersEx(),
- tp.x, tp.y, me.getClickCount(),
- me.isPopupTrigger(),
- me.getButton());
- tempComponent = lastComponentEntered;
- lastComponentEntered = null;
- tempComponent.dispatchEvent(exited);
+ target = target.getParent();
}
- // If we have a candidate, maybe enter it.
- if (candidate != null)
+ if (target != null)
{
- mouseEventTarget = candidate;
- if (candidate.isLightweight() && candidate.isShowing()
- && candidate != frame.getContentPane()
- && candidate != lastComponentEntered)
- {
- lastComponentEntered = mouseEventTarget;
- Point cp = SwingUtilities.convertPoint(frame.getContentPane(), x,
- y, lastComponentEntered);
- MouseEvent entered = new MouseEvent(lastComponentEntered,
- MouseEvent.MOUSE_ENTERED,
- me.getWhen(),
- me.getModifiersEx(), cp.x,
- cp.y, me.getClickCount(),
- me.isPopupTrigger(),
- me.getButton());
- lastComponentEntered.dispatchEvent(entered);
- }
- }
-
- if (me.getID() == MouseEvent.MOUSE_RELEASED
- || me.getID() == MouseEvent.MOUSE_PRESSED && pressCount > 0
- || me.getID() == MouseEvent.MOUSE_DRAGGED)
- // If any of the following events occur while a button is held down,
- // they should be dispatched to the same component to which the
- // original MOUSE_PRESSED event was dispatched:
- // - MOUSE_RELEASED
- // - MOUSE_PRESSED: another button pressed while the first is held down
- // - MOUSE_DRAGGED
- mouseEventTarget = pressedComponent;
- else if (me.getID() == MouseEvent.MOUSE_CLICKED)
- {
- // Don't dispatch CLICKED events whose target is not the same as the
- // target for the original PRESSED event.
- if (candidate != pressedComponent)
- mouseEventTarget = null;
- else if (pressCount == 0)
- pressedComponent = null;
+ int id = e.getID();
+ switch (id)
+ {
+ case MouseEvent.MOUSE_ENTERED:
+ // Now redispatch the thing.
+ if (! isDragging || frame.isSelected())
+ {
+ mouseEventTarget = target;
+ redispatch(id, e, mouseEventTarget);
+ }
+ break;
+ case MouseEvent.MOUSE_EXITED:
+ if (! isDragging || frame.isSelected())
+ {
+ redispatch(id, e, mouseEventTarget);
+ }
+ break;
+ case MouseEvent.MOUSE_PRESSED:
+ mouseEventTarget = target;
+ redispatch(id, e, mouseEventTarget);
+ // Start dragging.
+ dragTarget = target;
+ break;
+ case MouseEvent.MOUSE_RELEASED:
+ if (isDragging)
+ {
+ redispatch(id, e, dragTarget);
+ isDragging = false;
+ }
+ else
+ redispatch(id, e, mouseEventTarget);
+ break;
+ case MouseEvent.MOUSE_CLICKED:
+ redispatch(id, e, mouseEventTarget);
+ break;
+ case MouseEvent.MOUSE_MOVED:
+ if (target != mouseEventTarget)
+ {
+ // Create additional MOUSE_EXITED/MOUSE_ENTERED pairs.
+ redispatch(MouseEvent.MOUSE_EXITED, e, mouseEventTarget);
+ mouseEventTarget = target;
+ redispatch(MouseEvent.MOUSE_ENTERED, e, mouseEventTarget);
+ }
+ redispatch(id, e, mouseEventTarget);
+ break;
+ case MouseEvent.MOUSE_DRAGGED:
+ if (! isDragging)
+ isDragging = true;
+ redispatch(id, e, mouseEventTarget);
+ break;
+ case MouseEvent.MOUSE_WHEEL:
+ redispatch(id, e, mouseEventTarget);
+ break;
+ default:
+ assert false : "Must not reach here";
+ }
}
}
/**
- * This is a helper method that dispatches the GlassPane MouseEvents to the
- * proper component.
- *
- * @param e
- * The AWTEvent to be dispatched. Usually an instance of
- * MouseEvent.
+ * Redispatches the event to the real target with the specified id.
+ *
+ * @param id the new event ID
+ * @param e the original event
+ * @param target the real event target
*/
- private void handleEvent(AWTEvent e)
+ private void redispatch(int id, MouseEvent e, Component target)
{
- if (e instanceof MouseEvent)
- {
- MouseEvent me = (MouseEvent) e;
- acquireComponentForMouseEvent(me);
-
- //If there is no target, return
- if (mouseEventTarget == null)
- return;
-
- //Avoid re-dispatching to ourselves and causing an infinite loop
- if (mouseEventTarget.equals(frame.getGlassPane()))
- return;
-
- // Avoid dispatching ENTERED and EXITED events twice.
- if (mouseEventTarget.isShowing()
- && e.getID() != MouseEvent.MOUSE_ENTERED
- && e.getID() != MouseEvent.MOUSE_EXITED)
- {
- MouseEvent newEvt = SwingUtilities.convertMouseEvent(
- frame.getGlassPane(),
- me,
- mouseEventTarget);
- mouseEventTarget.dispatchEvent(newEvt);
-
- switch (e.getID())
- {
- case MouseEvent.MOUSE_PRESSED:
- if (pressCount++ == 0)
- pressedComponent = mouseEventTarget;
- break;
- case MouseEvent.MOUSE_RELEASED:
- // Clear our memory of the original PRESSED event, only if
- // we're not expecting a CLICKED event after this. If
- // there is a CLICKED event after this, it will do clean up.
- if (--pressCount == 0 && mouseEventTarget != pressedComponent)
- pressedComponent = null;
- break;
- }
- }
- }
+ Point p = SwingUtilities.convertPoint(frame.getLayeredPane(), e.getX(),
+ e.getY(), target);
+ MouseEvent ev = new MouseEvent(target, id, e.getWhen(),
+ e.getModifiers() | e.getModifiersEx(),
+ p.x, p.y, e.getClickCount(),
+ e.isPopupTrigger());
+ target.dispatchEvent(ev);
}
}
@@ -962,10 +908,17 @@ public class BasicInternalFrameUI extends InternalFrameUI
}
else if (property.equals(JInternalFrame.IS_SELECTED_PROPERTY))
{
+ Component glassPane = frame.getGlassPane();
if (frame.isSelected())
- activateFrame(frame);
+ {
+ activateFrame(frame);
+ glassPane.setVisible(false);
+ }
else
- deactivateFrame(frame);
+ {
+ deactivateFrame(frame);
+ glassPane.setVisible(true);
+ }
}
else if (property.equals(JInternalFrame.ROOT_PANE_PROPERTY)
|| property.equals(JInternalFrame.GLASS_PANE_PROPERTY))
@@ -990,17 +943,25 @@ public class BasicInternalFrameUI extends InternalFrameUI
{
if (evt.getNewValue() == Boolean.TRUE)
{
+ Container parent = frame.getParent();
+ if (parent != null)
+ parent.removeComponentListener(componentListener);
closeFrame(frame);
}
}
- /*
- * FIXME: need to add ancestor properties to JComponents. else if
- * (evt.getPropertyName().equals(JComponent.ANCESTOR_PROPERTY)) { if
- * (desktopPane != null)
- * desktopPane.removeComponentListener(componentListener); desktopPane =
- * frame.getDesktopPane(); if (desktopPane != null)
- * desktopPane.addComponentListener(componentListener); }
- */
+ else if (property.equals("ancestor"))
+ {
+ Container newParent = (Container) evt.getNewValue();
+ Container oldParent = (Container) evt.getOldValue();
+ if (newParent != null)
+ {
+ newParent.addComponentListener(componentListener);
+ }
+ else if (oldParent != null)
+ {
+ oldParent.removeComponentListener(componentListener);
+ }
+ }
}
}
@@ -1299,6 +1260,12 @@ public class BasicInternalFrameUI extends InternalFrameUI
frame.addPropertyChangeListener(propertyChangeListener);
frame.getRootPane().getGlassPane().addMouseListener(glassPaneDispatcher);
frame.getRootPane().getGlassPane().addMouseMotionListener(glassPaneDispatcher);
+
+ Container parent = frame.getParent();
+ if (parent != null)
+ {
+ parent.addComponentListener(componentListener);
+ }
}
/**
@@ -1327,8 +1294,13 @@ public class BasicInternalFrameUI extends InternalFrameUI
*/
protected void uninstallListeners()
{
- if (desktopPane != null)
- desktopPane.removeComponentListener(componentListener);
+
+ Container parent = frame.getParent();
+ if (parent != null)
+ {
+ parent.removeComponentListener(componentListener);
+ }
+ componentListener = null;
frame.getRootPane().getGlassPane().removeMouseMotionListener(glassPaneDispatcher);
frame.getRootPane().getGlassPane().removeMouseListener(glassPaneDispatcher);
@@ -1339,7 +1311,7 @@ public class BasicInternalFrameUI extends InternalFrameUI
frame.removeMouseListener(borderListener);
propertyChangeListener = null;
- componentListener = null;
+
borderListener = null;
internalFrameListener = null;
glassPaneDispatcher = null;
diff --git a/javax/swing/plaf/basic/BasicListUI.java b/javax/swing/plaf/basic/BasicListUI.java
index 10f86ebda..493fc0578 100644
--- a/javax/swing/plaf/basic/BasicListUI.java
+++ b/javax/swing/plaf/basic/BasicListUI.java
@@ -479,7 +479,8 @@ public class BasicListUI extends ListUI
*/
public void mousePressed(MouseEvent event)
{
- // TODO: What should be done here, if anything?
+ // We need to explicitly request focus.
+ list.requestFocusInWindow();
}
/**
@@ -1210,7 +1211,7 @@ public class BasicListUI extends ListUI
boolean hasFocus = (list.getLeadSelectionIndex() == row) && BasicListUI.this.list.hasFocus();
Component comp = rend.getListCellRendererComponent(list,
data.getElementAt(row),
- 0, isSel, hasFocus);
+ row, isSel, hasFocus);
rendererPane.paintComponent(g, comp, list, bounds);
}
diff --git a/javax/swing/plaf/basic/BasicLookAndFeel.java b/javax/swing/plaf/basic/BasicLookAndFeel.java
index 1fffcddca..c056a2403 100644
--- a/javax/swing/plaf/basic/BasicLookAndFeel.java
+++ b/javax/swing/plaf/basic/BasicLookAndFeel.java
@@ -1031,6 +1031,25 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"PopupMenu.border", new BorderUIResource.BevelBorderUIResource(0),
"PopupMenu.font", new FontUIResource("Dialog", Font.PLAIN, 12),
"PopupMenu.foreground", new ColorUIResource(darkShadow),
+ "PopupMenu.selectedWindowInputMapBindings",
+ new Object[] {"ESCAPE", "cancel",
+ "DOWN", "selectNext",
+ "KP_DOWN", "selectNext",
+ "UP", "selectPrevious",
+ "KP_UP", "selectPrevious",
+ "LEFT", "selectParent",
+ "KP_LEFT", "selectParent",
+ "RIGHT", "selectChild",
+ "KP_RIGHT", "selectChild",
+ "ENTER", "return",
+ "SPACE", "return"
+ },
+ "PopupMenu.selectedWindowInputMapBindings.RightToLeft",
+ new Object[] {"LEFT", "selectChild",
+ "KP_LEFT", "selectChild",
+ "RIGHT", "selectParent",
+ "KP_RIGHT", "selectParent",
+ },
"ProgressBar.background", new ColorUIResource(Color.LIGHT_GRAY),
"ProgressBar.border",
new BorderUIResource.LineBorderUIResource(Color.GREEN, 2),
diff --git a/javax/swing/plaf/basic/BasicMenuBarUI.java b/javax/swing/plaf/basic/BasicMenuBarUI.java
index f258ebe30..cd25a3baf 100644
--- a/javax/swing/plaf/basic/BasicMenuBarUI.java
+++ b/javax/swing/plaf/basic/BasicMenuBarUI.java
@@ -38,24 +38,31 @@ exception statement from your version. */
package javax.swing.plaf.basic;
-import gnu.classpath.NotImplementedException;
-
import java.awt.Dimension;
+import java.awt.event.ActionEvent;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.ActionMap;
import javax.swing.BoxLayout;
+import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.LookAndFeel;
import javax.swing.MenuElement;
+import javax.swing.MenuSelectionManager;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.MouseInputListener;
+import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.MenuBarUI;
@@ -64,6 +71,47 @@ import javax.swing.plaf.MenuBarUI;
*/
public class BasicMenuBarUI extends MenuBarUI
{
+
+ /**
+ * This action is performed for the action command 'takeFocus'.
+ */
+ private static class FocusAction
+ extends AbstractAction
+ {
+
+ /**
+ * Creates a new FocusAction.
+ */
+ FocusAction()
+ {
+ super("takeFocus");
+ }
+
+ /**
+ * Performs the action.
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ // In the JDK this action seems to pop up the first menu of the
+ // menu bar.
+ JMenuBar menuBar = (JMenuBar) event.getSource();
+ MenuSelectionManager defaultManager =
+ MenuSelectionManager.defaultManager();
+ MenuElement me[];
+ MenuElement subElements[];
+ JMenu menu = menuBar.getMenu(0);
+ if (menu != null)
+ {
+ me = new MenuElement[3];
+ me[0] = (MenuElement) menuBar;
+ me[1] = (MenuElement) menu;
+ me[2] = (MenuElement) menu.getPopupMenu();
+ defaultManager.setSelectedPath(me);
+ }
+ }
+
+ }
+
protected ChangeListener changeListener;
/*ContainerListener that listens to the ContainerEvents fired from menu bar*/
@@ -178,9 +226,46 @@ public class BasicMenuBarUI extends MenuBarUI
* This method installs the keyboard actions for the JMenuBar.
*/
protected void installKeyboardActions()
- throws NotImplementedException
{
- // FIXME: implement
+ // Install InputMap.
+ Object[] bindings =
+ (Object[]) SharedUIDefaults.get("MenuBar.windowBindings");
+ InputMap inputMap = LookAndFeel.makeComponentInputMap(menuBar, bindings);
+ SwingUtilities.replaceUIInputMap(menuBar,
+ JComponent.WHEN_IN_FOCUSED_WINDOW,
+ inputMap);
+
+ // Install ActionMap.
+ SwingUtilities.replaceUIActionMap(menuBar, getActionMap());
+ }
+
+ /**
+ * Creates and returns the shared action map for JTrees.
+ *
+ * @return the shared action map for JTrees
+ */
+ private ActionMap getActionMap()
+ {
+ ActionMap am = (ActionMap) UIManager.get("MenuBar.actionMap");
+ if (am == null)
+ {
+ am = createDefaultActions();
+ UIManager.getLookAndFeelDefaults().put("MenuBar.actionMap", am);
+ }
+ return am;
+ }
+
+ /**
+ * Creates the default actions when there are none specified by the L&F.
+ *
+ * @return the default actions
+ */
+ private ActionMap createDefaultActions()
+ {
+ ActionMapUIResource am = new ActionMapUIResource();
+ Action action = new FocusAction();
+ am.put(action.getValue(Action.NAME), action);
+ return am;
}
/**
@@ -226,9 +311,10 @@ public class BasicMenuBarUI extends MenuBarUI
* This method reverses the work done in installKeyboardActions.
*/
protected void uninstallKeyboardActions()
- throws NotImplementedException
{
- // FIXME: implement.
+ SwingUtilities.replaceUIInputMap(menuBar,
+ JComponent.WHEN_IN_FOCUSED_WINDOW, null);
+ SwingUtilities.replaceUIActionMap(menuBar, null);
}
/**
diff --git a/javax/swing/plaf/basic/BasicMenuItemUI.java b/javax/swing/plaf/basic/BasicMenuItemUI.java
index c5ed2ff7e..6110aca66 100644
--- a/javax/swing/plaf/basic/BasicMenuItemUI.java
+++ b/javax/swing/plaf/basic/BasicMenuItemUI.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package javax.swing.plaf.basic;
+import gnu.classpath.SystemProperties;
+
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
@@ -256,8 +258,11 @@ public class BasicMenuItemUI extends MenuItemUI
map.put(accelerator, "doClick");
}
// TextLayout caching for speed-up drawing of text.
- else if (property.equals(AbstractButton.TEXT_CHANGED_PROPERTY)
- || property.equals("font"))
+ else if ((property.equals(AbstractButton.TEXT_CHANGED_PROPERTY)
+ || property.equals("font"))
+ && SystemProperties.getProperty("gnu.javax.swing.noGraphics2D")
+ == null)
+
{
AbstractButton b = (AbstractButton) e.getSource();
String text = b.getText();
@@ -406,10 +411,6 @@ public class BasicMenuItemUI extends MenuItemUI
{
ArrayList path = new ArrayList();
- // Path to menu should also include its popup menu.
- if (menuItem instanceof JMenu)
- path.add(((JMenu) menuItem).getPopupMenu());
-
Component c = menuItem;
while (c instanceof MenuElement)
{
diff --git a/javax/swing/plaf/basic/BasicMenuUI.java b/javax/swing/plaf/basic/BasicMenuUI.java
index 7d8784fd1..355e0435e 100644
--- a/javax/swing/plaf/basic/BasicMenuUI.java
+++ b/javax/swing/plaf/basic/BasicMenuUI.java
@@ -41,16 +41,22 @@ package javax.swing.plaf.basic;
import gnu.classpath.NotImplementedException;
import java.awt.Component;
+import java.awt.Container;
import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeListener;
+import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPopupMenu;
import javax.swing.LookAndFeel;
+import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
+import javax.swing.Timer;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
@@ -69,6 +75,32 @@ import javax.swing.plaf.ComponentUI;
*/
public class BasicMenuUI extends BasicMenuItemUI
{
+ /**
+ * Selects a menu. This is used to delay menu selection.
+ */
+ class SelectMenuAction
+ extends AbstractAction
+ {
+ /**
+ * Performs the action.
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ JMenu menu = (JMenu) menuItem;
+ MenuSelectionManager defaultManager =
+ MenuSelectionManager.defaultManager();
+ MenuElement path[] = defaultManager.getSelectedPath();
+ if(path.length > 0 && path[path.length - 1] == menu)
+ {
+ MenuElement newPath[] = new MenuElement[path.length + 1];
+ System.arraycopy(path, 0, newPath, 0, path.length);
+ newPath[path.length] = menu.getPopupMenu();
+ defaultManager.setSelectedPath(newPath);
+ }
+ }
+
+ }
+
protected ChangeListener changeListener;
/* MenuListener listens to MenuEvents fired by JMenu */
@@ -201,6 +233,7 @@ public class BasicMenuUI extends BasicMenuItemUI
*/
protected void installDefaults()
{
+
LookAndFeel.installBorder(menuItem, "Menu.border");
LookAndFeel.installColorsAndFont(menuItem, "Menu.background",
"Menu.foreground", "Menu.font");
@@ -212,6 +245,7 @@ public class BasicMenuUI extends BasicMenuItemUI
selectionForeground = UIManager.getColor("Menu.selectionForeground");
arrowIcon = UIManager.getIcon("Menu.arrowIcon");
oldBorderPainted = UIManager.getBoolean("Menu.borderPainted");
+ ((JMenu) menuItem).setDelay(200);
}
/**
@@ -234,9 +268,10 @@ public class BasicMenuUI extends BasicMenuItemUI
}
protected void setupPostTimer(JMenu menu)
- throws NotImplementedException
{
- // TODO: Implement this properly.
+ Timer timer = new Timer(menu.getDelay(), new SelectMenuAction());
+ timer.setRepeats(false);
+ timer.start();
}
/**
@@ -285,8 +320,7 @@ public class BasicMenuUI extends BasicMenuItemUI
{
public void mouseClicked(MouseEvent e)
{
- MenuSelectionManager manager = MenuSelectionManager.defaultManager();
- manager.processMouseEvent(e);
+ // Nothing to do here.
}
public void mouseDragged(MouseEvent e)
@@ -313,29 +347,46 @@ public class BasicMenuUI extends BasicMenuItemUI
public void mouseEntered(MouseEvent e)
{
- /* When mouse enters menu item, it should be considered selected
-
- if (i) if this menu is a submenu in some other menu
- (ii) or if this menu is in a menu bar and some other menu in a
- menu bar was just selected and has its popup menu visible.
- (If nothing was selected, menu should be pressed before
- it will be selected)
- */
JMenu menu = (JMenu) menuItem;
-
- // NOTE: the following if used to require !menu.isArmed but I could find
- // no reason for this and it was preventing some JDK-compatible behaviour.
- // Specifically, if a menu is selected but its popup menu not visible,
- // and then another menu is selected whose popup menu IS visible, when
- // the mouse is moved over the first menu, its popup menu should become
- // visible.
-
- if (! menu.isTopLevelMenu() || popupVisible())
+ if (menu.isEnabled())
{
- // set new selection and forward this event to MenuSelectionManager
- MenuSelectionManager manager = MenuSelectionManager.defaultManager();
- manager.setSelectedPath(getPath());
- manager.processMouseEvent(e);
+ MenuSelectionManager manager =
+ MenuSelectionManager.defaultManager();
+ MenuElement[] selectedPath = manager.getSelectedPath();
+ if (! menu.isTopLevelMenu())
+ {
+ // Open the menu immediately or delayed, depending on the
+ // delay value.
+ if(! (selectedPath.length > 0
+ && selectedPath[selectedPath.length - 1] == menu.getPopupMenu()))
+ {
+ if(menu.getDelay() == 0)
+ {
+ MenuElement[] path = getPath();
+ MenuElement[] newPath = new MenuElement[path.length + 1];
+ System.arraycopy(path, 0, newPath, 0, path.length);
+ newPath[path.length] = menu.getPopupMenu();
+ manager.setSelectedPath(newPath);
+ }
+ else
+ {
+ manager.setSelectedPath(getPath());
+ setupPostTimer(menu);
+ }
+ }
+ }
+ else
+ {
+ if(selectedPath.length > 0
+ && selectedPath[0] == menu.getParent())
+ {
+ MenuElement[] newPath = new MenuElement[3];
+ newPath[0] = (MenuElement) menu.getParent();
+ newPath[1] = menu;
+ newPath[2] = menu.getPopupMenu();
+ manager.setSelectedPath(newPath);
+ }
+ }
}
}
@@ -354,29 +405,48 @@ public class BasicMenuUI extends BasicMenuItemUI
{
MenuSelectionManager manager = MenuSelectionManager.defaultManager();
JMenu menu = (JMenu) menuItem;
- manager.processMouseEvent(e);
-
- // Menu should be displayed when the menu is pressed only if
- // it is top-level menu
- if (menu.isTopLevelMenu())
+ if (menu.isEnabled())
{
- if (menu.getPopupMenu().isVisible())
- // If menu is visible and menu button was pressed..
- // then need to cancel the menu
- manager.clearSelectedPath();
- else
- {
- // Display the menu
- int x = 0;
- int y = menu.getHeight();
-
- manager.setSelectedPath(getPath());
-
- JMenuBar mb = (JMenuBar) menu.getParent();
-
- // set selectedIndex of the selectionModel of a menuBar
- mb.getSelectionModel().setSelectedIndex(mb.getComponentIndex(menu));
- }
+ // Open up the menu immediately if it's a toplevel menu.
+ // But not yet the popup, which might be opened delayed, see below.
+ if (menu.isTopLevelMenu())
+ {
+ if (menu.isSelected())
+ manager.clearSelectedPath();
+ else
+ {
+ Container cnt = menu.getParent();
+ if (cnt != null && cnt instanceof JMenuBar)
+ {
+ MenuElement[] me = new MenuElement[2];
+ me[0] = (MenuElement) cnt;
+ me[1] = menu;
+ manager.setSelectedPath(me);
+ }
+ }
+ }
+
+ // Open the menu's popup. Either do that immediately if delay == 0,
+ // or delayed when delay > 0.
+ MenuElement[] selectedPath = manager.getSelectedPath();
+ if (selectedPath.length > 0
+ && selectedPath[selectedPath.length - 1] != menu.getPopupMenu())
+ {
+ if(menu.isTopLevelMenu() || menu.getDelay() == 0)
+ {
+ MenuElement[] newPath =
+ new MenuElement[selectedPath.length + 1];
+ System.arraycopy(selectedPath, 0, newPath, 0,
+ selectedPath.length);
+ newPath[selectedPath.length] = menu.getPopupMenu();
+ manager.setSelectedPath(newPath);
+ }
+ else
+ {
+ setupPostTimer(menu);
+ }
+ }
+
}
}
@@ -493,8 +563,44 @@ public class BasicMenuUI extends BasicMenuItemUI
*/
public void menuDragMouseDragged(MenuDragMouseEvent e)
{
- MenuSelectionManager manager = MenuSelectionManager.defaultManager();
- manager.setSelectedPath(e.getPath());
+ if (menuItem.isEnabled())
+ {
+ MenuSelectionManager manager = e.getMenuSelectionManager();
+ MenuElement path[] = e.getPath();
+
+ Point p = e.getPoint();
+ if(p.x >= 0 && p.x < menuItem.getWidth()
+ && p.y >= 0 && p.y < menuItem.getHeight())
+ {
+ JMenu menu = (JMenu) menuItem;
+ MenuElement[] selectedPath = manager.getSelectedPath();
+ if(! (selectedPath.length > 0
+ && selectedPath[selectedPath.length-1]
+ == menu.getPopupMenu()))
+ {
+ if(menu.isTopLevelMenu() || menu.getDelay() == 0
+ || e.getID() == MouseEvent.MOUSE_DRAGGED)
+ {
+ MenuElement[] newPath = new MenuElement[path.length + 1];
+ System.arraycopy(path, 0, newPath, 0, path.length);
+ newPath[path.length] = menu.getPopupMenu();
+ manager.setSelectedPath(newPath);
+ }
+ else
+ {
+ manager.setSelectedPath(path);
+ setupPostTimer(menu);
+ }
+ }
+ }
+ else if (e.getID() == MouseEvent.MOUSE_RELEASED)
+ {
+ Component comp = manager.componentForPoint(e.getComponent(),
+ e.getPoint());
+ if (comp == null)
+ manager.clearSelectedPath();
+ }
+ }
}
/**
@@ -505,8 +611,7 @@ public class BasicMenuUI extends BasicMenuItemUI
*/
public void menuDragMouseEntered(MenuDragMouseEvent e)
{
- MenuSelectionManager manager = MenuSelectionManager.defaultManager();
- manager.setSelectedPath(e.getPath());
+ // Nothing to do here.
}
/**
diff --git a/javax/swing/plaf/basic/BasicOptionPaneUI.java b/javax/swing/plaf/basic/BasicOptionPaneUI.java
index 27bcb8c46..e23808580 100644
--- a/javax/swing/plaf/basic/BasicOptionPaneUI.java
+++ b/javax/swing/plaf/basic/BasicOptionPaneUI.java
@@ -38,13 +38,12 @@ exception statement from your version. */
package javax.swing.plaf.basic;
-import gnu.classpath.NotImplementedException;
-
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
+import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
@@ -58,10 +57,14 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyVetoException;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
+import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
@@ -76,6 +79,7 @@ import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
+import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.OptionPaneUI;
@@ -85,6 +89,21 @@ import javax.swing.plaf.OptionPaneUI;
public class BasicOptionPaneUI extends OptionPaneUI
{
/**
+ * Implements the "close" keyboard action.
+ */
+ static class OptionPaneCloseAction
+ extends AbstractAction
+ {
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JOptionPane op = (JOptionPane) event.getSource();
+ op.setValue(new Integer(JOptionPane.CLOSED_OPTION));
+ }
+
+ }
+
+ /**
* This is a helper class that listens to the buttons located at the bottom
* of the JOptionPane.
*
@@ -389,36 +408,20 @@ public class BasicOptionPaneUI extends OptionPaneUI
*/
public void propertyChange(PropertyChangeEvent e)
{
- if (e.getPropertyName().equals(JOptionPane.ICON_PROPERTY)
- || e.getPropertyName().equals(JOptionPane.MESSAGE_TYPE_PROPERTY))
- addIcon(messageAreaContainer);
- else if (e.getPropertyName().equals(JOptionPane.INITIAL_SELECTION_VALUE_PROPERTY))
- resetSelectedValue();
- else if (e.getPropertyName().equals(JOptionPane.INITIAL_VALUE_PROPERTY)
- || e.getPropertyName().equals(JOptionPane.OPTIONS_PROPERTY)
- || e.getPropertyName().equals(JOptionPane.OPTION_TYPE_PROPERTY))
- {
- Container newButtons = createButtonArea();
- optionPane.remove(buttonContainer);
- optionPane.add(newButtons);
- buttonContainer = newButtons;
- }
-
- else if (e.getPropertyName().equals(JOptionPane.MESSAGE_PROPERTY)
- || e.getPropertyName().equals(JOptionPane.WANTS_INPUT_PROPERTY)
- || e.getPropertyName().equals(JOptionPane.SELECTION_VALUES_PROPERTY))
+ String property = e.getPropertyName();
+ if (property.equals(JOptionPane.ICON_PROPERTY)
+ || property.equals(JOptionPane.INITIAL_SELECTION_VALUE_PROPERTY)
+ || property.equals(JOptionPane.INITIAL_VALUE_PROPERTY)
+ || property.equals(JOptionPane.MESSAGE_PROPERTY)
+ || property.equals(JOptionPane.MESSAGE_TYPE_PROPERTY)
+ || property.equals(JOptionPane.OPTION_TYPE_PROPERTY)
+ || property.equals(JOptionPane.OPTIONS_PROPERTY)
+ || property.equals(JOptionPane.WANTS_INPUT_PROPERTY))
{
- optionPane.remove(messageAreaContainer);
- messageAreaContainer = createMessageArea();
- optionPane.add(messageAreaContainer);
- Container newButtons = createButtonArea();
- optionPane.remove(buttonContainer);
- optionPane.add(newButtons);
- buttonContainer = newButtons;
- optionPane.add(buttonContainer);
+ uninstallComponents();
+ installComponents();
+ optionPane.validate();
}
- optionPane.invalidate();
- optionPane.repaint();
}
}
@@ -462,15 +465,6 @@ public class BasicOptionPaneUI extends OptionPaneUI
/** The size of the icons. */
private static final int ICON_SIZE = 36;
- /** The foreground color for the message area. */
- private transient Color messageForeground;
-
- /** The border around the message area. */
- private transient Border messageBorder;
-
- /** The border around the button area. */
- private transient Border buttonBorder;
-
/** The string used to describe OK buttons. */
private static final String OK_STRING = "OK";
@@ -700,6 +694,7 @@ public class BasicOptionPaneUI extends OptionPaneUI
if (icon != null)
{
iconLabel = new JLabel(icon);
+ configureLabel(iconLabel);
top.add(iconLabel, BorderLayout.WEST);
}
}
@@ -761,7 +756,9 @@ public class BasicOptionPaneUI extends OptionPaneUI
}
else if (msg instanceof Icon)
{
- container.add(new JLabel((Icon) msg), cons);
+ JLabel label = new JLabel((Icon) msg);
+ configureLabel(label);
+ container.add(label, cons);
cons.gridy++;
}
else
@@ -778,8 +775,11 @@ public class BasicOptionPaneUI extends OptionPaneUI
addMessageComponents(container, cons, tmp, maxll, true);
}
else
- addMessageComponents(container, cons, new JLabel(msg.toString()),
- maxll, true);
+ {
+ JLabel label = new JLabel(msg.toString());
+ configureLabel(label);
+ addMessageComponents(container, cons, label, maxll, true);
+ }
}
}
@@ -810,6 +810,7 @@ public class BasicOptionPaneUI extends OptionPaneUI
remainder = d.substring(maxll);
}
JLabel label = new JLabel(line);
+ configureLabel(label);
c.add(label);
// If there is nothing left to burst, then we can stop.
@@ -820,8 +821,12 @@ public class BasicOptionPaneUI extends OptionPaneUI
if (remainder.length() > maxll || remainder.contains("\n"))
burstStringInto(c, remainder, maxll);
else
- // Add the remainder to the container and be done.
- c.add(new JLabel(remainder));
+ {
+ // Add the remainder to the container and be done.
+ JLabel l = new JLabel(remainder);
+ configureLabel(l);
+ c.add(l);
+ }
}
/**
@@ -857,6 +862,9 @@ public class BasicOptionPaneUI extends OptionPaneUI
protected Container createButtonArea()
{
JPanel buttonPanel = new JPanel();
+ Border b = UIManager.getBorder("OptionPane.buttonAreaBorder");
+ if (b != null)
+ buttonPanel.setBorder(b);
buttonPanel.setLayout(createLayoutManager());
addButtonComponents(buttonPanel, getButtons(), getInitialValueIndex());
@@ -882,6 +890,10 @@ public class BasicOptionPaneUI extends OptionPaneUI
protected Container createMessageArea()
{
JPanel messageArea = new JPanel();
+ Border messageBorder = UIManager.getBorder("OptionPane.messageAreaBorder");
+ if (messageBorder != null)
+ messageArea.setBorder(messageBorder);
+
messageArea.setLayout(new BorderLayout());
addIcon(messageArea);
@@ -935,10 +947,10 @@ public class BasicOptionPaneUI extends OptionPaneUI
* @return A Container that will separate the message and button areas.
*/
protected Container createSeparator()
- throws NotImplementedException
{
- // FIXME: Figure out what this method is supposed to return and where
- // this should be added to the OptionPane.
+ // The reference implementation returns null here. When overriding
+ // to return something non-null, the component gets added between
+ // the message area and the button area. See installComponents().
return null;
}
@@ -1139,35 +1151,17 @@ public class BasicOptionPaneUI extends OptionPaneUI
*/
protected void installComponents()
{
- // reset it.
- hasCustomComponents = false;
- Container msg = createMessageArea();
- if (msg != null)
- {
- ((JComponent) msg).setBorder(messageBorder);
- msg.setForeground(messageForeground);
- messageAreaContainer = msg;
- optionPane.add(msg);
- }
+ // First thing is the message area.
+ optionPane.add(createMessageArea());
- // FIXME: Figure out if the separator should be inserted here or what
- // this thing is supposed to do. Note: The JDK does NOT insert another
- // component at this place. The JOptionPane only has two panels in it
- // and there actually are applications that depend on this beeing so.
+ // Add separator when createSeparator() is overridden to return
+ // something other than null.
Container sep = createSeparator();
if (sep != null)
optionPane.add(sep);
- Container button = createButtonArea();
- if (button != null)
- {
- ((JComponent) button).setBorder(buttonBorder);
- buttonContainer = button;
- optionPane.add(button);
- }
-
- optionPane.setBorder(BorderFactory.createEmptyBorder(12, 12, 11, 11));
- optionPane.invalidate();
+ // Last thing is the button area.
+ optionPane.add(createButtonArea());
}
/**
@@ -1181,10 +1175,6 @@ public class BasicOptionPaneUI extends OptionPaneUI
LookAndFeel.installBorder(optionPane, "OptionPane.border");
optionPane.setOpaque(true);
- messageBorder = UIManager.getBorder("OptionPane.messageAreaBorder");
- messageForeground = UIManager.getColor("OptionPane.messageForeground");
- buttonBorder = UIManager.getBorder("OptionPane.buttonAreaBorder");
-
minimumSize = UIManager.getDimension("OptionPane.minimumSize");
// FIXME: Image icons don't seem to work properly right now.
@@ -1202,9 +1192,44 @@ public class BasicOptionPaneUI extends OptionPaneUI
* This method installs keyboard actions for the JOptionpane.
*/
protected void installKeyboardActions()
- throws NotImplementedException
{
- // FIXME: implement.
+ // Install the input map.
+ Object[] bindings =
+ (Object[]) SharedUIDefaults.get("OptionPane.windowBindings");
+ InputMap inputMap = LookAndFeel.makeComponentInputMap(optionPane,
+ bindings);
+ SwingUtilities.replaceUIInputMap(optionPane,
+ JComponent.WHEN_IN_FOCUSED_WINDOW,
+ inputMap);
+
+ // FIXME: The JDK uses a LazyActionMap for parentActionMap
+ SwingUtilities.replaceUIActionMap(optionPane, getActionMap());
+ }
+
+ /**
+ * Fetches the action map from the UI defaults, or create a new one
+ * if the action map hasn't been initialized.
+ *
+ * @return the action map
+ */
+ private ActionMap getActionMap()
+ {
+ ActionMap am = (ActionMap) UIManager.get("OptionPane.actionMap");
+ if (am == null)
+ {
+ am = createDefaultActions();
+ UIManager.getLookAndFeelDefaults().put("OptionPane.actionMap", am);
+ }
+ return am;
+ }
+
+ private ActionMap createDefaultActions()
+ {
+ ActionMapUIResource am = new ActionMapUIResource();
+ Action action = new OptionPaneCloseAction();
+
+ am.put("close", action);
+ return am;
}
/**
@@ -1317,10 +1342,6 @@ public class BasicOptionPaneUI extends OptionPaneUI
minimumSize = null;
- messageBorder = null;
- buttonBorder = null;
- messageForeground = null;
-
// FIXME: ImageIcons don't seem to work properly
/*
@@ -1335,9 +1356,10 @@ public class BasicOptionPaneUI extends OptionPaneUI
* This method uninstalls keyboard actions for the JOptionPane.
*/
protected void uninstallKeyboardActions()
- throws NotImplementedException
{
- // FIXME: implement.
+ SwingUtilities.replaceUIInputMap(optionPane, JComponent.
+ WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);
+ SwingUtilities.replaceUIActionMap(optionPane, null);
}
/**
@@ -1363,4 +1385,20 @@ public class BasicOptionPaneUI extends OptionPaneUI
optionPane = null;
}
+
+ /**
+ * Applies the proper UI configuration to labels that are added to
+ * the OptionPane.
+ *
+ * @param l the label to configure
+ */
+ private void configureLabel(JLabel l)
+ {
+ Color c = UIManager.getColor("OptionPane.messageForeground");
+ if (c != null)
+ l.setForeground(c);
+ Font f = UIManager.getFont("OptionPane.messageFont");
+ if (f != null)
+ l.setFont(f);
+ }
}
diff --git a/javax/swing/plaf/basic/BasicPopupMenuUI.java b/javax/swing/plaf/basic/BasicPopupMenuUI.java
index 5ceaecb91..8c0fe6757 100644
--- a/javax/swing/plaf/basic/BasicPopupMenuUI.java
+++ b/javax/swing/plaf/basic/BasicPopupMenuUI.java
@@ -37,33 +37,574 @@ exception statement from your version. */
package javax.swing.plaf.basic;
-import gnu.classpath.NotImplementedException;
-
import java.awt.Component;
import java.awt.Dimension;
+import java.awt.KeyboardFocusManager;
+import java.awt.event.ActionEvent;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
+import java.util.EventListener;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.ActionMap;
import javax.swing.BoxLayout;
+import javax.swing.InputMap;
+import javax.swing.JApplet;
import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
+import javax.swing.JRootPane;
import javax.swing.LookAndFeel;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
+import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.PopupMenuUI;
-
/**
* UI Delegate for JPopupMenu
*/
public class BasicPopupMenuUI extends PopupMenuUI
{
+ /**
+ * Handles keyboard navigation through menus.
+ */
+ private static class NavigateAction
+ extends AbstractAction
+ {
+
+ /**
+ * Creates a new NavigateAction instance.
+ *
+ * @param name the name of the action
+ */
+ NavigateAction(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Actually performs the action.
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ String name = (String) getValue(Action.NAME);
+ if (name.equals("selectNext"))
+ navigateNextPrevious(true);
+ else if (name.equals("selectPrevious"))
+ navigateNextPrevious(false);
+ else if (name.equals("selectChild"))
+ navigateParentChild(true);
+ else if (name.equals("selectParent"))
+ navigateParentChild(false);
+ else if (name.equals("cancel"))
+ cancel();
+ else if (name.equals("return"))
+ doReturn();
+ else
+ assert false : "Must not reach here";
+ }
+
+ /**
+ * Navigates to the next or previous menu item.
+ *
+ * @param dir <code>true</code>: navigate to next, <code>false</code>:
+ * navigate to previous
+ */
+ private void navigateNextPrevious(boolean dir)
+ {
+ MenuSelectionManager msm = MenuSelectionManager.defaultManager();
+ MenuElement path[] = msm.getSelectedPath();
+ int len = path.length;
+ if (len >= 2)
+ {
+
+ if (path[0] instanceof JMenuBar &&
+ path[1] instanceof JMenu && len == 2)
+ {
+
+ // A toplevel menu is selected, but its popup not yet shown.
+ // Show the popup and select the first item
+ JPopupMenu popup = ((JMenu)path[1]).getPopupMenu();
+ MenuElement next =
+ findEnabledChild(popup.getSubElements(), -1, true);
+ MenuElement[] newPath;
+
+ if (next != null)
+ {
+ newPath = new MenuElement[4];
+ newPath[3] = next;
+ }
+ else
+ {
+ // Menu has no enabled items, show the popup anyway.
+ newPath = new MenuElement[3];
+ }
+ System.arraycopy(path, 0, newPath, 0, 2);
+ newPath[2] = popup;
+ msm.setSelectedPath(newPath);
+ }
+ else if (path[len - 1] instanceof JPopupMenu &&
+ path[len - 2] instanceof JMenu)
+ {
+ // Select next item in already shown popup menu.
+ JMenu menu = (JMenu) path[len - 2];
+ JPopupMenu popup = menu.getPopupMenu();
+ MenuElement next =
+ findEnabledChild(popup.getSubElements(), -1, dir);
+
+ if (next != null)
+ {
+ MenuElement[] newPath = new MenuElement[len + 1];
+ System.arraycopy(path, 0, newPath, 0, len);
+ newPath[len] = next;
+ msm.setSelectedPath(newPath);
+ }
+ else
+ {
+ // All items in the popup are disabled.
+ // Find the parent popup menu and select
+ // its next item. If there's no parent popup menu , do nothing.
+ if (len > 2 && path[len - 3] instanceof JPopupMenu)
+ {
+ popup = ((JPopupMenu) path[len - 3]);
+ next = findEnabledChild(popup.getSubElements(),
+ menu, dir);
+ if (next != null && next != menu)
+ {
+ MenuElement[] newPath = new MenuElement[len - 1];
+ System.arraycopy(path, 0, newPath, 0, len - 2);
+ newPath[len - 2] = next;
+ msm.setSelectedPath(newPath);
+ }
+ }
+ }
+ }
+ else
+ {
+ // Only select the next item.
+ MenuElement subs[] = path[len - 2].getSubElements();
+ MenuElement nextChild =
+ findEnabledChild(subs, path[len - 1], dir);
+ if (nextChild == null)
+ {
+ nextChild = findEnabledChild(subs, -1, dir);
+ }
+ if (nextChild != null)
+ {
+ path[len-1] = nextChild;
+ msm.setSelectedPath(path);
+ }
+ }
+ }
+ }
+
+ private MenuElement findEnabledChild(MenuElement[] children,
+ MenuElement start, boolean dir)
+ {
+ MenuElement found = null;
+ for (int i = 0; i < children.length && found == null; i++)
+ {
+ if (children[i] == start)
+ {
+ found = findEnabledChild(children, i, dir);
+ }
+ }
+ return found;
+ }
+
+ /**
+ * Searches the next or previous enabled child menu element.
+ *
+ * @param children the children to search through
+ * @param start the index at which to start
+ * @param dir the direction (true == forward, false == backward)
+ *
+ * @return the found element or null
+ */
+ private MenuElement findEnabledChild(MenuElement[] children,
+ int start, boolean dir)
+ {
+ MenuElement result = null;
+ if (dir)
+ {
+ result = findNextEnabledChild(children, start + 1, children.length-1);
+ if (result == null)
+ result = findNextEnabledChild(children, 0, start - 1);
+ }
+ else
+ {
+ result = findPreviousEnabledChild(children, start - 1, 0);
+ if (result == null)
+ result = findPreviousEnabledChild(children, children.length-1,
+ start + 1);
+ }
+ return result;
+ }
+
+ /**
+ * Finds the next child element that is enabled and visible.
+ *
+ * @param children the children to search through
+ * @param start the start index
+ * @param end the end index
+ *
+ * @return the found child, or null
+ */
+ private MenuElement findNextEnabledChild(MenuElement[] children, int start,
+ int end)
+ {
+ MenuElement found = null;
+ for (int i = start; i <= end && found == null; i++)
+ {
+ if (children[i] != null)
+ {
+ Component comp = children[i].getComponent();
+ if (comp != null && comp.isEnabled() && comp.isVisible())
+ {
+ found = children[i];
+ }
+ }
+ }
+ return found;
+ }
+
+ /**
+ * Finds the previous child element that is enabled and visible.
+ *
+ * @param children the children to search through
+ * @param start the start index
+ * @param end the end index
+ *
+ * @return the found child, or null
+ */
+ private MenuElement findPreviousEnabledChild(MenuElement[] children,
+ int start, int end)
+ {
+ MenuElement found = null;
+ for (int i = start; i >= end && found == null; i--)
+ {
+ if (children[i] != null)
+ {
+ Component comp = children[i].getComponent();
+ if (comp != null && comp.isEnabled() && comp.isVisible())
+ {
+ found = children[i];
+ }
+ }
+ }
+ return found;
+ }
+
+ /**
+ * Navigates to the parent or child menu item.
+ *
+ * @param selectChild <code>true</code>: navigate to child,
+ * <code>false</code>: navigate to parent
+ */
+ private void navigateParentChild(boolean selectChild)
+ {
+ MenuSelectionManager msm = MenuSelectionManager.defaultManager();
+ MenuElement path[] = msm.getSelectedPath();
+ int len = path.length;
+
+ if (selectChild)
+ {
+ if (len > 0 && path[len - 1] instanceof JMenu
+ && ! ((JMenu) path[len-1]).isTopLevelMenu())
+ {
+ // We have a submenu, open it.
+ JMenu menu = (JMenu) path[len - 1];
+ JPopupMenu popup = menu.getPopupMenu();
+ MenuElement[] subs = popup.getSubElements();
+ MenuElement item = findEnabledChild(subs, -1, true);
+ MenuElement[] newPath;
+
+ if (item == null)
+ {
+ newPath = new MenuElement[len + 1];
+ }
+ else
+ {
+ newPath = new MenuElement[len + 2];
+ newPath[len + 1] = item;
+ }
+ System.arraycopy(path, 0, newPath, 0, len);
+ newPath[len] = popup;
+ msm.setSelectedPath(newPath);
+ return;
+ }
+ }
+ else
+ {
+ int popupIndex = len-1;
+ if (len > 2
+ && (path[popupIndex] instanceof JPopupMenu
+ || path[--popupIndex] instanceof JPopupMenu)
+ && ! ((JMenu) path[popupIndex - 1]).isTopLevelMenu())
+ {
+ // We have a submenu, close it.
+ MenuElement newPath[] = new MenuElement[popupIndex];
+ System.arraycopy(path, 0, newPath, 0, popupIndex);
+ msm.setSelectedPath(newPath);
+ return;
+ }
+ }
+
+ // If we got here, we have not selected a child or parent.
+ // Check if we have a toplevel menu selected. If so, then select
+ // another one.
+ if (len > 1 && path[0] instanceof JMenuBar)
+ {
+ MenuElement currentMenu = path[1];
+ MenuElement nextMenu = findEnabledChild(path[0].getSubElements(),
+ currentMenu, selectChild);
+
+ if (nextMenu != null && nextMenu != currentMenu)
+ {
+ MenuElement newSelection[];
+ if (len == 2)
+ {
+ // Menu is selected but its popup not shown.
+ newSelection = new MenuElement[2];
+ newSelection[0] = path[0];
+ newSelection[1] = nextMenu;
+ }
+ else
+ {
+ // Menu is selected and its popup is shown.
+ newSelection = new MenuElement[3];
+ newSelection[0] = path[0];
+ newSelection[1] = nextMenu;
+ newSelection[2] = ((JMenu) nextMenu).getPopupMenu();
+ }
+ msm.setSelectedPath(newSelection);
+ }
+ }
+ }
+
+ /**
+ * Handles cancel requests (ESC key).
+ */
+ private void cancel()
+ {
+ // Fire popup menu cancelled event. Unfortunately the
+ // firePopupMenuCancelled() is protected in JPopupMenu so we work
+ // around this limitation by fetching the listeners and notifying them
+ // directly.
+ JPopupMenu lastPopup = (JPopupMenu) getLastPopup();
+ EventListener[] ll = lastPopup.getListeners(PopupMenuListener.class);
+ for (int i = 0; i < ll.length; i++)
+ {
+ PopupMenuEvent ev = new PopupMenuEvent(lastPopup);
+ ((PopupMenuListener) ll[i]).popupMenuCanceled(ev);
+ }
+
+ // Close the last popup or the whole selection if there's only one
+ // popup left.
+ MenuSelectionManager msm = MenuSelectionManager.defaultManager();
+ MenuElement path[] = msm.getSelectedPath();
+ if(path.length > 4)
+ {
+ MenuElement newPath[] = new MenuElement[path.length - 2];
+ System.arraycopy(path,0,newPath,0,path.length-2);
+ MenuSelectionManager.defaultManager().setSelectedPath(newPath);
+ }
+ else
+ msm.clearSelectedPath();
+ }
+
+ /**
+ * Returns the last popup menu in the current selection or null.
+ *
+ * @return the last popup menu in the current selection or null
+ */
+ private JPopupMenu getLastPopup()
+ {
+ MenuSelectionManager msm = MenuSelectionManager.defaultManager();
+ MenuElement[] p = msm.getSelectedPath();
+ JPopupMenu popup = null;
+ for(int i = p.length - 1; popup == null && i >= 0; i--)
+ {
+ if (p[i] instanceof JPopupMenu)
+ popup = (JPopupMenu) p[i];
+ }
+ return popup;
+ }
+
+ /**
+ * Handles ENTER key requests. This normally opens submenus on JMenu
+ * items, or activates the menu item as if it's been clicked on it.
+ */
+ private void doReturn()
+ {
+ KeyboardFocusManager fmgr =
+ KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ Component focusOwner = fmgr.getFocusOwner();
+ if((focusOwner == null || (focusOwner instanceof JRootPane)))
+ {
+ MenuSelectionManager msm = MenuSelectionManager.defaultManager();
+ MenuElement path[] = msm.getSelectedPath();
+ MenuElement lastElement;
+ if(path.length > 0)
+ {
+ lastElement = path[path.length - 1];
+ if(lastElement instanceof JMenu)
+ {
+ MenuElement newPath[] = new MenuElement[path.length + 1];
+ System.arraycopy(path,0,newPath,0,path.length);
+ newPath[path.length] = ((JMenu) lastElement).getPopupMenu();
+ msm.setSelectedPath(newPath);
+ }
+ else if(lastElement instanceof JMenuItem)
+ {
+ JMenuItem mi = (JMenuItem)lastElement;
+ if (mi.getUI() instanceof BasicMenuItemUI)
+ {
+ ((BasicMenuItemUI)mi.getUI()).doClick(msm);
+ }
+ else
+ {
+ msm.clearSelectedPath();
+ mi.doClick(0);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Installs keyboard actions when a popup is opened, and uninstalls the
+ * keyboard actions when closed. This listens on the default
+ * MenuSelectionManager.
+ */
+ private class KeyboardHelper
+ implements ChangeListener
+ {
+ private MenuElement[] lastSelectedPath = new MenuElement[0];
+ private Component lastFocused;
+ private JRootPane invokerRootPane;
+
+ public void stateChanged(ChangeEvent event)
+ {
+ MenuSelectionManager msm = (MenuSelectionManager) event.getSource();
+ MenuElement[] p = msm.getSelectedPath();
+ JPopupMenu popup = getActivePopup(p);
+ if (popup == null || popup.isFocusable())
+ {
+ if (lastSelectedPath.length != 0 && p.length != 0 )
+ {
+ if (! invokerEquals(p[0], lastSelectedPath[0]))
+ {
+ uninstallKeyboardActionsImpl();
+ lastSelectedPath = new MenuElement[0];
+ }
+ }
+
+ if (lastSelectedPath.length == 0 && p.length > 0)
+ {
+ JComponent invoker;
+ if (popup == null)
+ {
+ if (p.length == 2 && p[0] instanceof JMenuBar
+ && p[1] instanceof JMenu)
+ {
+ // A menu has been selected but not opened.
+ invoker = (JComponent)p[1];
+ popup = ((JMenu)invoker).getPopupMenu();
+ }
+ else
+ {
+ return;
+ }
+ }
+ else
+ {
+ Component c = popup.getInvoker();
+ if(c instanceof JFrame)
+ {
+ invoker = ((JFrame) c).getRootPane();
+ }
+ else if(c instanceof JApplet)
+ {
+ invoker = ((JApplet) c).getRootPane();
+ }
+ else
+ {
+ while (!(c instanceof JComponent))
+ {
+ if (c == null)
+ {
+ return;
+ }
+ c = c.getParent();
+ }
+ invoker = (JComponent)c;
+ }
+ }
+
+ // Remember current focus owner.
+ lastFocused = KeyboardFocusManager.
+ getCurrentKeyboardFocusManager().getFocusOwner();
+
+ // Install keybindings used for menu navigation.
+ invokerRootPane = SwingUtilities.getRootPane(invoker);
+ if (invokerRootPane != null)
+ {
+ invokerRootPane.requestFocus(true);
+ installKeyboardActionsImpl();
+ }
+ }
+ else if (lastSelectedPath.length != 0 && p.length == 0)
+ {
+ // menu hidden -- return focus to where it had been before
+ // and uninstall menu keybindings
+ uninstallKeyboardActionsImpl();
+ }
+ }
+
+ // Remember the last path selected
+ lastSelectedPath = p;
+ }
+
+ private JPopupMenu getActivePopup(MenuElement[] path)
+ {
+ JPopupMenu active = null;
+ for (int i = path.length - 1; i >= 0 && active == null; i--)
+ {
+ MenuElement elem = path[i];
+ if (elem instanceof JPopupMenu)
+ {
+ active = (JPopupMenu) elem;
+ }
+ }
+ return active;
+ }
+
+ private boolean invokerEquals(MenuElement el1, MenuElement el2)
+ {
+ Component invoker1 = el1.getComponent();
+ Component invoker2 = el2.getComponent();
+ if (invoker1 instanceof JPopupMenu)
+ invoker1 = ((JPopupMenu) invoker1).getInvoker();
+ if (invoker2 instanceof JPopupMenu)
+ invoker2 = ((JPopupMenu) invoker2).getInvoker();
+ return invoker1 == invoker2;
+ }
+ }
+
/* popupMenu for which this UI delegate is for*/
protected JPopupMenu popupMenu;
@@ -75,6 +616,19 @@ public class BasicPopupMenuUI extends PopupMenuUI
TopWindowListener topWindowListener;
/**
+ * Counts how many popup menus are handled by this UI or a subclass.
+ * This is used to install a KeyboardHelper on the MenuSelectionManager
+ * for the first popup, and uninstall this same KeyboardHelper when the
+ * last popup is uninstalled.
+ */
+ private static int numPopups;
+
+ /**
+ * This is the KeyboardHelper that listens on the MenuSelectionManager.
+ */
+ private static KeyboardHelper keyboardHelper;
+
+ /**
* Creates a new BasicPopupMenuUI object.
*/
public BasicPopupMenuUI()
@@ -106,6 +660,16 @@ public class BasicPopupMenuUI extends PopupMenuUI
public void installUI(JComponent c)
{
super.installUI(c);
+
+ // Install KeyboardHelper when the first popup is initialized.
+ if (numPopups == 0)
+ {
+ keyboardHelper = new KeyboardHelper();
+ MenuSelectionManager msm = MenuSelectionManager.defaultManager();
+ msm.addChangeListener(keyboardHelper);
+ }
+ numPopups++;
+
popupMenu = (JPopupMenu) c;
popupMenu.setLayout(new DefaultMenuLayout(popupMenu, BoxLayout.Y_AXIS));
popupMenu.setBorderPainted(true);
@@ -113,6 +677,7 @@ public class BasicPopupMenuUI extends PopupMenuUI
installDefaults();
installListeners();
+ installKeyboardActions();
}
/**
@@ -139,9 +704,77 @@ public class BasicPopupMenuUI extends PopupMenuUI
* This method installs the keyboard actions for this {@link JPopupMenu}.
*/
protected void installKeyboardActions()
- throws NotImplementedException
{
- // FIXME: Need to implement
+ // We can't install the keyboard actions here, because then all
+ // popup menus would have their actions registered in the KeyboardManager.
+ // So we install it when the popup menu is opened, and uninstall it
+ // when it's closed. This is done in the KeyboardHelper class.
+ // Install InputMap.
+ }
+
+ /**
+ * Called by the KeyboardHandler when a popup is made visible.
+ */
+ void installKeyboardActionsImpl()
+ {
+ Object[] bindings;
+ if (popupMenu.getComponentOrientation().isLeftToRight())
+ {
+ bindings = (Object[])
+ SharedUIDefaults.get("PopupMenu.selectedWindowInputMapBindings");
+ }
+ else
+ {
+ bindings = (Object[]) SharedUIDefaults.get
+ ("PopupMenu.selectedWindowInputMapBindings.RightToLeft");
+ }
+ InputMap inputMap = LookAndFeel.makeComponentInputMap(popupMenu, bindings);
+ SwingUtilities.replaceUIInputMap(popupMenu,
+ JComponent.WHEN_IN_FOCUSED_WINDOW,
+ inputMap);
+
+ // Install ActionMap.
+ SwingUtilities.replaceUIActionMap(popupMenu, getActionMap());
+ }
+
+ /**
+ * Creates and returns the shared action map for JTrees.
+ *
+ * @return the shared action map for JTrees
+ */
+ private ActionMap getActionMap()
+ {
+ ActionMap am = (ActionMap) UIManager.get("PopupMenu.actionMap");
+ if (am == null)
+ {
+ am = createDefaultActions();
+ UIManager.getLookAndFeelDefaults().put("PopupMenu.actionMap", am);
+ }
+ return am;
+ }
+
+ /**
+ * Creates the default actions when there are none specified by the L&F.
+ *
+ * @return the default actions
+ */
+ private ActionMap createDefaultActions()
+ {
+ ActionMapUIResource am = new ActionMapUIResource();
+ Action action = new NavigateAction("selectNext");
+ am.put(action.getValue(Action.NAME), action);
+ action = new NavigateAction("selectPrevious");
+ am.put(action.getValue(Action.NAME), action);
+ action = new NavigateAction("selectParent");
+ am.put(action.getValue(Action.NAME), action);
+ action = new NavigateAction("selectChild");
+ am.put(action.getValue(Action.NAME), action);
+ action = new NavigateAction("return");
+ am.put(action.getValue(Action.NAME), action);
+ action = new NavigateAction("cancel");
+ am.put(action.getValue(Action.NAME), action);
+
+ return am;
}
/**
@@ -155,7 +788,17 @@ public class BasicPopupMenuUI extends PopupMenuUI
{
uninstallListeners();
uninstallDefaults();
+ uninstallKeyboardActions();
popupMenu = null;
+
+ // Install KeyboardHelper when the first popup is initialized.
+ numPopups--;
+ if (numPopups == 0)
+ {
+ MenuSelectionManager msm = MenuSelectionManager.defaultManager();
+ msm.removeChangeListener(keyboardHelper);
+ }
+
}
/**
@@ -182,9 +825,22 @@ public class BasicPopupMenuUI extends PopupMenuUI
* Uninstalls any keyboard actions.
*/
protected void uninstallKeyboardActions()
- throws NotImplementedException
{
- // FIXME: Need to implement
+ // We can't install the keyboard actions here, because then all
+ // popup menus would have their actions registered in the KeyboardManager.
+ // So we install it when the popup menu is opened, and uninstall it
+ // when it's closed. This is done in the KeyboardHelper class.
+ // Install InputMap.
+ }
+
+ /**
+ * Called by the KeyboardHandler when a popup is made invisible.
+ */
+ void uninstallKeyboardActionsImpl()
+ {
+ SwingUtilities.replaceUIInputMap(popupMenu,
+ JComponent.WHEN_IN_FOCUSED_WINDOW, null);
+ SwingUtilities.replaceUIActionMap(popupMenu, null);
}
/**
diff --git a/javax/swing/plaf/basic/BasicScrollBarUI.java b/javax/swing/plaf/basic/BasicScrollBarUI.java
index 78e5168fc..ee246cbba 100644
--- a/javax/swing/plaf/basic/BasicScrollBarUI.java
+++ b/javax/swing/plaf/basic/BasicScrollBarUI.java
@@ -1228,8 +1228,12 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
protected void scrollByBlock(int direction)
{
+ if (direction > 0)
scrollbar.setValue(scrollbar.getValue()
+ scrollbar.getBlockIncrement(direction));
+ else
+ scrollbar.setValue(scrollbar.getValue()
+ - scrollbar.getBlockIncrement(direction));
}
/**
@@ -1239,8 +1243,12 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
*/
protected void scrollByUnit(int direction)
{
- scrollbar.setValue(scrollbar.getValue()
- + scrollbar.getUnitIncrement(direction));
+ if (direction > 0)
+ scrollbar.setValue(scrollbar.getValue()
+ + scrollbar.getUnitIncrement(direction));
+ else
+ scrollbar.setValue(scrollbar.getValue()
+ - scrollbar.getUnitIncrement(direction));
}
/**
diff --git a/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/javax/swing/plaf/basic/BasicTabbedPaneUI.java
index 17fa6075b..11f25167d 100644
--- a/javax/swing/plaf/basic/BasicTabbedPaneUI.java
+++ b/javax/swing/plaf/basic/BasicTabbedPaneUI.java
@@ -1,5 +1,5 @@
/* BasicTabbedPaneUI.java --
- Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,8 +38,6 @@ exception statement from your version. */
package javax.swing.plaf.basic;
-import gnu.classpath.NotImplementedException;
-
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
@@ -51,6 +49,7 @@ import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Point;
import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
@@ -60,7 +59,10 @@ import java.awt.event.MouseListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
+import javax.swing.AbstractAction;
+import javax.swing.ActionMap;
import javax.swing.Icon;
+import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
@@ -72,6 +74,7 @@ import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
+import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.PanelUI;
import javax.swing.plaf.TabbedPaneUI;
@@ -80,11 +83,127 @@ import javax.swing.text.View;
/**
* This is the Basic Look and Feel's UI delegate for JTabbedPane.
+ *
+ * @author Lillian Angel (langel@redhat.com)
+ * @author Kim Ho (kho@redhat.com)
+ * @author Roman Kennke (kennke@aicas.com)
+ * @author Robert Schuster (robertschuster@fsfe.org)
*/
public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
{
+
+ static class NavigateAction extends AbstractAction
+ {
+ int direction;
+
+ NavigateAction(String name, int dir)
+ {
+ super(name);
+ direction = dir;
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTabbedPane tp = (JTabbedPane) event.getSource();
+ BasicTabbedPaneUI ui = (BasicTabbedPaneUI) tp.getUI();
+
+ ui.navigateSelectedTab(direction);
+ }
+
+ }
+
+ static class NavigatePageDownAction extends AbstractAction
+ {
+
+ public NavigatePageDownAction()
+ {
+ super("navigatePageDown");
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTabbedPane tp = (JTabbedPane) event.getSource();
+ BasicTabbedPaneUI ui = (BasicTabbedPaneUI) tp.getUI();
+
+ int i = tp.getSelectedIndex();
+
+ if (i < 0)
+ i = 0;
+
+ ui.selectNextTabInRun(i);
+ }
+
+ }
+
+ static class NavigatePageUpAction extends AbstractAction
+ {
+
+ public NavigatePageUpAction()
+ {
+ super("navigatePageUp");
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTabbedPane tp = (JTabbedPane) event.getSource();
+ BasicTabbedPaneUI ui = (BasicTabbedPaneUI) tp.getUI();
+
+ int i = tp.getSelectedIndex();
+
+ if (i < 0)
+ i = 0;
+
+ ui.selectPreviousTabInRun(i);
+
+ }
+ }
+
+ static class RequestFocusAction extends AbstractAction
+ {
+
+ public RequestFocusAction()
+ {
+ super("requestFocus");
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ ((JTabbedPane) event.getSource()).requestFocus();
+ }
+
+ }
+
+ static class RequestFocusForVisibleComponentAction extends AbstractAction
+ {
+
+ public RequestFocusForVisibleComponentAction()
+ {
+ super("requestFocusForVisibleComponent");
+ }
+
+ public void actionPerformed(ActionEvent event)
+ {
+ JTabbedPane tp = (JTabbedPane) event.getSource();
+
+ // FIXME: This should select a suitable component within
+ // the tab content. However I dont know whether we have
+ // to search for this component or wether the called is
+ // supposed to do that.
+ tp.getSelectedComponent().requestFocus();
+ }
+
+ }
+
/**
- * A helper class that handles focus.
+ * A helper class that handles focus.
+ * <p>The purpose of this class is to implement a more flexible focus
+ * handling for the tabbed pane, which is used to determine whether the
+ * focus indicator should be painted or not. When in scrolling layout
+ * mode the area containing the tabs is a scrollpane, so simply testing
+ * whether the tabbed pane has the focus does not work.</p>
+ * <p>The <code>FocusHandler</code> is installed on the scrollpane and
+ * the tabbed pane and sets the variable <code>hasFocus</code> to
+ * <code>false</code> only when both components do not hold the focus.</p>
*
* @specnote Apparently this class was intended to be protected,
* but was made public by a compiler bug and is now
@@ -98,9 +217,12 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
* @param e The FocusEvent.
*/
public void focusGained(FocusEvent e)
- throws NotImplementedException
{
- // FIXME: Implement.
+ Object source = e.getSource();
+ if (source == panel )
+ tabPane.requestFocus();
+ else if (source == tabPane)
+ tabPane.repaint();
}
/**
@@ -109,9 +231,11 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
* @param e The FocusEvent.
*/
public void focusLost(FocusEvent e)
- throws NotImplementedException
{
- // FIXME: Implement.
+ if (e.getOppositeComponent() == tabPane.getSelectedComponent())
+ tabPane.requestFocus();
+ else if (e.getSource() == tabPane)
+ tabPane.repaint();
}
}
@@ -126,6 +250,11 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
public class MouseHandler extends MouseAdapter
{
+ public void mouseReleased(MouseEvent e)
+ {
+ // Nothing to do here.
+ }
+
/**
* This method is called when the mouse is pressed. The index cannot
* change to a tab that is not enabled.
@@ -134,14 +263,84 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
public void mousePressed(MouseEvent e)
{
- if (tabPane.isEnabled())
+ Object s = e.getSource();
+ int placement = tabPane.getTabPlacement();
+
+ if (s == incrButton)
{
- int index = tabForCoordinate(tabPane, e.getX(), e.getY());
- if (index >= 0 && tabPane.isEnabledAt(index))
+ if(!incrButton.isEnabled())
+ return;
+
+ currentScrollLocation++;
+
+ switch (placement)
{
- tabPane.setSelectedIndex(index);
+ case JTabbedPane.TOP:
+ case JTabbedPane.BOTTOM:
+ currentScrollOffset = getTabAreaInsets(placement).left;
+ for (int i = 0; i < currentScrollLocation; i++)
+ currentScrollOffset += rects[i].width;
+ break;
+ default:
+ currentScrollOffset = getTabAreaInsets(placement).top;
+ for (int i = 0; i < currentScrollLocation; i++)
+ currentScrollOffset += rects[i].height;
+ break;
}
+
+ updateViewPosition();
+ updateButtons();
+
+ tabPane.repaint();
+ }
+ else if (s == decrButton)
+ {
+ if(!decrButton.isEnabled())
+ return;
+
+ // The scroll location may be zero but the offset
+ // greater than zero because of an adjustement to
+ // make a partially visible tab completely visible.
+ if (currentScrollLocation > 0)
+ currentScrollLocation--;
+
+ // Set the offset back to 0 and recompute it.
+ currentScrollOffset = 0;
+
+ switch (placement)
+ {
+ case JTabbedPane.TOP:
+ case JTabbedPane.BOTTOM:
+ // Take the tab area inset into account.
+ if (currentScrollLocation > 0)
+ currentScrollOffset = getTabAreaInsets(placement).left;
+ // Recompute scroll offset.
+ for (int i = 0; i < currentScrollLocation; i++)
+ currentScrollOffset += rects[i].width;
+ break;
+ default:
+ // Take the tab area inset into account.
+ if (currentScrollLocation > 0)
+ currentScrollOffset = getTabAreaInsets(placement).top;
+
+ for (int i = 0; i < currentScrollLocation; i++)
+ currentScrollOffset += rects[i].height;
+ }
+
+ updateViewPosition();
+ updateButtons();
+
+ tabPane.repaint();
+ } else if (tabPane.isEnabled())
+ {
+ int index = tabForCoordinate(tabPane, e.getX(), e.getY());
+ if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT
+ && s == panel)
+ scrollTab(index, placement);
+
+ tabPane.setSelectedIndex(index);
}
+
}
/**
@@ -199,6 +398,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
{
if (e.getPropertyName().equals("tabLayoutPolicy"))
{
+ currentScrollLocation = currentScrollOffset = 0;
+
layoutManager = createLayoutManager();
tabPane.setLayout(layoutManager);
@@ -267,7 +468,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
// Find out the minimum/preferred size to display the largest child
// of the tabbed pane.
- for (int i = 0; i < tabPane.getTabCount(); i++)
+ int count = tabPane.getTabCount();
+ for (int i = 0; i < count; i++)
{
c = tabPane.getComponentAt(i);
if (c == null)
@@ -284,21 +486,19 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
{
- int min = calculateMaxTabWidth(tabPlacement);
- width = Math.max(min, width);
- int tabAreaHeight = preferredTabAreaHeight(tabPlacement,
- width - tabAreaInsets.left
- - tabAreaInsets.right);
- height += tabAreaHeight;
+ width = Math.max(calculateMaxTabWidth(tabPlacement), width);
+
+ height += preferredTabAreaHeight(tabPlacement,
+ width - tabAreaInsets.left
+ - tabAreaInsets.right);
}
else
{
- int min = calculateMaxTabHeight(tabPlacement);
- height = Math.max(min, height);
- int tabAreaWidth = preferredTabAreaWidth(tabPlacement,
- height - tabAreaInsets.top
- - tabAreaInsets.bottom);
- width += tabAreaWidth;
+ height = Math.max(calculateMaxTabHeight(tabPlacement), height);
+
+ width += preferredTabAreaWidth(tabPlacement,
+ height - tabAreaInsets.top
+ - tabAreaInsets.bottom);
}
Insets tabPaneInsets = tabPane.getInsets();
@@ -308,7 +508,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
// if tab placement is LEFT OR RIGHT, they share width.
// if tab placement is TOP OR BOTTOM, they share height
- // PRE STEP: finds the default sizes for the labels as well as their locations.
+ // PRE STEP: finds the default sizes for the labels as well as their
+ // locations.
// AND where they will be placed within the run system.
// 1. calls normalizeTab Runs.
// 2. calls rotate tab runs.
@@ -347,7 +548,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
break;
case RIGHT:
maxTabWidth = calculateMaxTabWidth(tabPlacement);
- x = size.width - (insets.right + tabAreaInsets.right) - maxTabWidth;
+ x = size.width - (insets.right + tabAreaInsets.right)
+ - maxTabWidth - 1;
y = insets.top + tabAreaInsets.top;
breakAt = size.height - (insets.bottom + tabAreaInsets.bottom);
break;
@@ -355,7 +557,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
maxTabHeight = calculateMaxTabHeight(tabPlacement);
x = insets.left + tabAreaInsets.left;
y = size.height - (insets.bottom + tabAreaInsets.bottom)
- - maxTabHeight;
+ - maxTabHeight - 1;
breakAt = size.width - (insets.right + tabAreaInsets.right);
break;
case TOP:
@@ -374,6 +576,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
runCount = 0;
selectedRun = -1;
int selectedIndex = tabPane.getSelectedIndex();
+ if (selectedIndex < 0)
+ selectedIndex = 0;
Rectangle rect;
@@ -411,7 +615,6 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
rect.height = maxTabHeight;
if (i == selectedIndex)
selectedRun = runCount - 1;
-
}
}
else
@@ -456,9 +659,9 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
int start;
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
- start = y;
- else
start = x;
+ else
+ start = y;
normalizeTabRuns(tabPlacement, tabCount, start, breakAt);
selectedRun = getRunForTab(tabCount, selectedIndex);
if (shouldRotateTabRuns(tabPlacement))
@@ -466,7 +669,11 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
rotateTabRuns(tabPlacement, selectedRun);
}
}
-
+
+ // Suppress padding if we have only one tab run.
+ if (runCount == 1)
+ return;
+
// Pad the runs.
int tabRunOverlay = getTabRunOverlay(tabPlacement);
for (int i = runCount - 1; i >= 0; --i)
@@ -606,16 +813,18 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
public Dimension minimumLayoutSize(Container parent)
{
- return calculateSize(false);
+ return calculateSize(true);
}
- // If there is more free space in an adjacent run AND the tab in the run can fit in the
- // adjacent run, move it. This method is not perfect, it is merely an approximation.
+ // If there is more free space in an adjacent run AND the tab
+ // in the run can fit in the adjacent run, move it. This method
+ // is not perfect, it is merely an approximation.
// If you play around with Sun's JTabbedPane, you'll see that
// it does do some pretty strange things with regards to not moving tabs
// that should be moved.
// start = the x position where the tabs will begin
- // max = the maximum position of where the tabs can go to (tabAreaInsets.left + the width of the tab area)
+ // max = the maximum position of where the tabs can go to
+ // (tabAreaInsets.left + the width of the tab area)
/**
* This method tries to "even out" the number of tabs in each run based on
@@ -633,18 +842,20 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPlacement == SwingUtilities.TOP
|| tabPlacement == SwingUtilities.BOTTOM)
{
- // We should only do this for runCount - 1, cause we can only shift that many times between
- // runs.
+ // We should only do this for runCount - 1, cause we can
+ // only shift that many times between runs.
for (int i = 1; i < runCount; i++)
{
Rectangle currRun = rects[lastTabInRun(tabCount, i)];
- Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))];
+ Rectangle nextRun = rects[lastTabInRun(tabCount,
+ getNextTabRun(i))];
int spaceInCurr = currRun.x + currRun.width;
int spaceInNext = nextRun.x + nextRun.width;
int diffNow = spaceInCurr - spaceInNext;
int diffLater = (spaceInCurr - currRun.width)
- (spaceInNext + currRun.width);
+
while (Math.abs(diffLater) < Math.abs(diffNow)
&& spaceInNext + currRun.width < max)
{
@@ -656,11 +867,12 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
diffLater = (spaceInCurr - currRun.width)
- (spaceInNext + currRun.width);
}
-
- // Fix the bounds.
- int first = lastTabInRun(tabCount, i) + 1;
- int last = lastTabInRun(tabCount, getNextTabRun(i));
- int currX = tabAreaInsets.left;
+
+ // Fixes the bounds of all tabs in the current
+ // run.
+ int first = tabRuns[i];
+ int last = lastTabInRun(tabCount, i);
+ int currX = start;
for (int j = first; j <= last; j++)
{
rects[j].x = currX;
@@ -673,7 +885,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
for (int i = 1; i < runCount; i++)
{
Rectangle currRun = rects[lastTabInRun(tabCount, i)];
- Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))];
+ Rectangle nextRun = rects[lastTabInRun(tabCount,
+ getNextTabRun(i))];
int spaceInCurr = currRun.y + currRun.height;
int spaceInNext = nextRun.y + nextRun.height;
@@ -692,9 +905,10 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
- (spaceInNext + currRun.height);
}
- int first = lastTabInRun(tabCount, i) + 1;
- int last = lastTabInRun(tabCount, getNextTabRun(i));
- int currY = tabAreaInsets.top;
+ // Fixes the bounds of tabs in the current run.
+ int first = tabRuns[i];
+ int last = lastTabInRun(tabCount, i);
+ int currY = start;
for (int j = first; j <= last; j++)
{
rects[j].y = currY;
@@ -720,7 +934,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
rects[selectedIndex].height += insets.top + insets.bottom;
}
- // If the tabs on the run don't fill the width of the window, make it fit now.
+ // If the tabs on the run don't fill the width of the window, make it
+ // fit now.
// start = starting index of the run
// end = last index of the run
// max = tabAreaInsets.left + width (or equivalent)
@@ -744,7 +959,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
int runWidth = rects[end].x + rects[end].width;
int spaceRemaining = max - runWidth;
int numTabs = end - start + 1;
-
+
// now divvy up the space.
int spaceAllocated = spaceRemaining / numTabs;
int currX = rects[start].x;
@@ -752,11 +967,13 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
{
rects[i].x = currX;
rects[i].width += spaceAllocated;
+
currX += rects[i].width;
// This is used because since the spaceAllocated
// variable is an int, it rounds down. Sometimes,
// we don't fill an entire row, so we make it do
// so now.
+
if (i == end && rects[i].x + rects[i].width != max)
rects[i].width = max - rects[i].x;
}
@@ -821,7 +1038,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
// The reason why we can't use runCount:
// This method is only called to calculate the size request
- // for the tabbedPane. However, this size request is dependent on
+ // for the tabbedPane. However, this size request is dependent on
// our desired width. We need to find out what the height would
// be IF we got our desired width.
for (int i = 0; i < tabPane.getTabCount(); i++)
@@ -884,7 +1101,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
runs++;
int maxTabWidth = calculateMaxTabWidth(tabPlacement);
- int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runs, maxTabWidth);
+ int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runs,
+ maxTabWidth);
return tabAreaWidth;
}
@@ -898,11 +1116,11 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
protected void rotateTabRuns(int tabPlacement, int selectedRun)
{
- if (runCount == 1 || selectedRun == 1 || selectedRun == -1)
+ if (runCount == 1 || selectedRun == 0 || selectedRun == -1)
return;
int[] newTabRuns = new int[tabRuns.length];
int currentRun = selectedRun;
- int i = 1;
+ int i = 0;
do
{
newTabRuns[i] = tabRuns[currentRun];
@@ -910,8 +1128,6 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
i++;
}
while (i < runCount);
- if (runCount > 1)
- newTabRuns[0] = tabRuns[currentRun];
tabRuns = newTabRuns;
BasicTabbedPaneUI.this.selectedRun = 1;
@@ -944,7 +1160,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
public Dimension preferredLayoutSize(Container parent)
{
- return super.calculateSize(true);
+ return super.calculateSize(false);
}
/**
@@ -1018,29 +1234,27 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
SwingUtilities.calculateInnerArea(tabPane, calcRect);
Insets tabAreaInsets = getTabAreaInsets(tabPlacement);
Insets insets = tabPane.getInsets();
- int runs = 1;
- int start = 0;
- int top = 0;
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
{
int maxHeight = calculateMaxTabHeight(tabPlacement);
calcRect.width -= tabAreaInsets.left + tabAreaInsets.right;
- start = tabAreaInsets.left + insets.left;
int width = 0;
- int runWidth = start;
- top = insets.top + tabAreaInsets.top;
+ int runWidth = tabAreaInsets.left + insets.left;
+ int top = insets.top + tabAreaInsets.top;
for (int i = 0; i < tabCount; i++)
{
width = calculateTabWidth(tabPlacement, i, fm);
-
- rects[i] = new Rectangle(runWidth, top, width, maxHeight);
+
+ // The proper instances should exists because
+ // assureRectsCreated() was being run already.
+ rects[i].setBounds(runWidth, top, width, maxHeight);
+
runWidth += width;
}
tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right;
- tabAreaRect.height = runs * maxTabHeight
- - (runs - 1) * tabRunOverlay
- + tabAreaInsets.top + tabAreaInsets.bottom;
+ tabAreaRect.height = maxTabHeight + tabAreaInsets.top
+ + tabAreaInsets.bottom;
contentRect.width = tabAreaRect.width;
contentRect.height = tabPane.getHeight() - insets.top
- insets.bottom - tabAreaRect.height;
@@ -1063,23 +1277,25 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom;
int height = 0;
- start = tabAreaInsets.top + insets.top;
- int runHeight = start;
+ int runHeight = tabAreaInsets.top + insets.top;;
int fontHeight = fm.getHeight();
- top = insets.left + tabAreaInsets.left;
+ int left = insets.left + tabAreaInsets.left;
for (int i = 0; i < tabCount; i++)
{
height = calculateTabHeight(tabPlacement, i, fontHeight);
- rects[i] = new Rectangle(top, runHeight, maxWidth, height);
+
+ // The proper instances should exists because
+ // assureRectsCreated() was being run already.
+ rects[i].setBounds(left, runHeight, maxWidth, height);
runHeight += height;
}
- tabAreaRect.width = runs * maxTabWidth - (runs - 1) * tabRunOverlay
- + tabAreaInsets.left + tabAreaInsets.right;
+ tabAreaRect.width = maxTabWidth + tabAreaInsets.left
+ + tabAreaInsets.right;
tabAreaRect.height = tabPane.getHeight() - insets.top
- - insets.bottom;
+ - insets.bottom;
tabAreaRect.y = insets.top;
contentRect.width = tabPane.getWidth() - insets.left - insets.right
- - tabAreaRect.width;
+ - tabAreaRect.width;
contentRect.height = tabAreaRect.height;
contentRect.y = insets.top;
if (tabPlacement == SwingConstants.LEFT)
@@ -1093,11 +1309,9 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
tabAreaRect.x = contentRect.x + contentRect.width;
}
}
- runCount = runs;
- if (runCount > tabRuns.length)
- expandTabRunsArray();
-
- padSelectedTab(tabPlacement, tabPane.getSelectedIndex());
+
+ // Unlike the behavior in the WRAP_TAB_LAYOUT the selected
+ // tab is not padded specially.
}
/**
@@ -1115,8 +1329,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabCount == 0)
return;
int tabPlacement = tabPane.getTabPlacement();
- incrButton.setVisible(false);
- decrButton.setVisible(false);
+
if (tabPlacement == SwingConstants.TOP
|| tabPlacement == SwingConstants.BOTTOM)
{
@@ -1126,18 +1339,49 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
Dimension incrDims = incrButton.getPreferredSize();
Dimension decrDims = decrButton.getPreferredSize();
- decrButton.setBounds(tabAreaRect.x + tabAreaRect.width
- - incrDims.width - decrDims.width,
- tabAreaRect.y, decrDims.width,
- tabAreaRect.height);
- incrButton.setBounds(tabAreaRect.x + tabAreaRect.width
- - incrDims.width, tabAreaRect.y,
- decrDims.width, tabAreaRect.height);
-
+ if (tabPlacement == SwingConstants.BOTTOM)
+ {
+ // Align scroll buttons with the bottom border of the tabbed
+ // pane's content area.
+ decrButton.setBounds(tabAreaRect.x + tabAreaRect.width
+ - incrDims.width - decrDims.width,
+ tabAreaRect.y, decrDims.width,
+ decrDims.height);
+ incrButton.setBounds(tabAreaRect.x + tabAreaRect.width
+ - incrDims.width, tabAreaRect.y,
+ incrDims.width, incrDims.height);
+ }
+ else
+ {
+ // Align scroll buttons with the top border of the tabbed
+ // pane's content area.
+ decrButton.setBounds(tabAreaRect.x + tabAreaRect.width
+ - incrDims.width - decrDims.width,
+ tabAreaRect.y + tabAreaRect.height
+ - decrDims.height, decrDims.width,
+ decrDims.height);
+ incrButton.setBounds(tabAreaRect.x + tabAreaRect.width
+ - incrDims.width,
+ tabAreaRect.y + tabAreaRect.height
+ - incrDims.height,
+ incrDims.width, incrDims.height);
+ }
+
tabAreaRect.width -= decrDims.width + incrDims.width;
+
+ updateButtons();
+
incrButton.setVisible(true);
decrButton.setVisible(true);
}
+ else
+ {
+ incrButton.setVisible(false);
+ decrButton.setVisible(false);
+
+ currentScrollOffset = 0;
+ currentScrollLocation = 0;
+ }
}
if (tabPlacement == SwingConstants.LEFT
@@ -1149,34 +1393,54 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
Dimension incrDims = incrButton.getPreferredSize();
Dimension decrDims = decrButton.getPreferredSize();
- decrButton.setBounds(tabAreaRect.x,
- tabAreaRect.y + tabAreaRect.height
- - incrDims.height - decrDims.height,
- tabAreaRect.width, decrDims.height);
- incrButton.setBounds(tabAreaRect.x,
- tabAreaRect.y + tabAreaRect.height
- - incrDims.height, tabAreaRect.width,
- incrDims.height);
+ if (tabPlacement == SwingConstants.RIGHT)
+ {
+ // Align scroll buttons with the right border of the tabbed
+ // pane's content area.
+ decrButton.setBounds(tabAreaRect.x,
+ tabAreaRect.y + tabAreaRect.height
+ - incrDims.height - decrDims.height,
+ decrDims.width, decrDims.height);
+ incrButton.setBounds(tabAreaRect.x,
+ tabAreaRect.y + tabAreaRect.height
+ - incrDims.height, incrDims.width,
+ incrDims.height);
+ }
+ else
+ {
+ // Align scroll buttons with the left border of the tabbed
+ // pane's content area.
+ decrButton.setBounds(tabAreaRect.x + tabAreaRect.width
+ - decrDims.width,
+ tabAreaRect.y + tabAreaRect.height
+ - incrDims.height - decrDims.height,
+ decrDims.width, decrDims.height);
+ incrButton.setBounds(tabAreaRect.x + tabAreaRect.width
+ - incrDims.width,
+ tabAreaRect.y + tabAreaRect.height
+ - incrDims.height, incrDims.width,
+ incrDims.height);
+ }
tabAreaRect.height -= decrDims.height + incrDims.height;
+
incrButton.setVisible(true);
decrButton.setVisible(true);
}
+ else
+ {
+ incrButton.setVisible(false);
+ decrButton.setVisible(false);
+
+ currentScrollOffset = 0;
+ currentScrollLocation = 0;
+ }
}
viewport.setBounds(tabAreaRect.x, tabAreaRect.y, tabAreaRect.width,
tabAreaRect.height);
- int tabC = tabPane.getTabCount() - 1;
- if (tabCount > 0)
- {
- int w = Math.max(rects[tabC].width + rects[tabC].x, tabAreaRect.width);
- int h = Math.max(rects[tabC].height, tabAreaRect.height);
- p = findPointForIndex(currentScrollLocation);
-
- // we want to cover that entire space so that borders that run under
- // the tab area don't show up when we move the viewport around.
- panel.setSize(w + p.x, h + p.y);
- }
- viewport.setViewPosition(p);
+
+ updateViewPosition();
+
viewport.repaint();
}
}
@@ -1200,7 +1464,9 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
{
selectedRun = getRunForTab(tabPane.getTabCount(),
tabPane.getSelectedIndex());
- tabPane.revalidate();
+
+ if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT)
+ tabPane.revalidate();
tabPane.repaint();
}
}
@@ -1226,7 +1492,17 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
public void paint(Graphics g, JComponent c)
{
- paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex());
+ int placement = tabPane.getTabPlacement();
+ g.setColor(highlight);
+ if (placement == SwingUtilities.TOP
+ || placement == SwingUtilities.BOTTOM)
+ g.fillRect(currentScrollOffset, 0,
+ tabAreaRect.width, tabAreaRect.height);
+ else
+ g.fillRect(0, currentScrollOffset,
+ tabAreaRect.width, tabAreaRect.height);
+
+ paintTabArea(g, placement, tabPane.getSelectedIndex());
}
}
@@ -1287,6 +1563,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
/** The starting visible tab in the run in SCROLL_TAB_MODE.
* This is package-private to avoid an accessor method. */
transient int currentScrollLocation;
+
+ transient int currentScrollOffset;
/** A reusable rectangle. */
protected Rectangle calcRect;
@@ -1342,16 +1620,11 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
/** The gap between text and label */
protected int textIconGap;
- // Keeps track of tab runs.
- // The organization of this array is as follows (lots of experimentation to
- // figure this out)
- // index 0 = furthest away from the component area (aka outer run)
- // index 1 = closest to component area (aka selected run)
- // index > 1 = listed in order leading from selected run to outer run.
- // each int in the array is the tab index + 1 (counting starts at 1)
- // for the last tab in the run. (same as the rects array)
-
- /** This array keeps track of which tabs are in which run. See above. */
+ /** This array keeps track of which tabs are in which run.
+ * <p>The value at index i denotes the index of the first tab in run i.</p>
+ * <p>If the value for any index (i > 0) is 0 then (i - 1) is the last
+ * run.</p>
+ */
protected int[] tabRuns;
/**
@@ -1430,7 +1703,13 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
* The currently visible component.
*/
private Component visibleComponent;
-
+
+ private Color selectedColor;
+
+ private Rectangle tempTextRect = new Rectangle();
+
+ private Rectangle tempIconRect = new Rectangle();
+
/**
* Creates a new BasicTabbedPaneUI object.
*/
@@ -1519,8 +1798,115 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
Point p = new Point(w, h);
return p;
}
+
+ /** TabbedPanes in scrolling mode should use this method to
+ * scroll properly to the tab given by the index argument.
+ *
+ * @param index The tab to scroll to.
+ * @param placement The tab's placement.
+ */
+ final void scrollTab(int index, int placement)
+ {
+ int diff;
+ if (index >= 0 && tabPane.isEnabledAt(index))
+ {
+ // If the user clicked on the last tab and that one was
+ // only partially visible shift the scroll offset to make
+ // it completely visible.
+ switch (placement)
+ {
+ case JTabbedPane.TOP:
+ case JTabbedPane.BOTTOM:
+ if ((diff = rects[index].x
+ + rects[index].width
+ - decrButton.getX() - currentScrollOffset) > 0)
+ currentScrollOffset += diff;
+ else if ((diff = rects[index].x - currentScrollOffset) < 0)
+ {
+ if (index == 0)
+ currentScrollOffset = 0;
+ else
+ currentScrollOffset += diff;
+ }
+
+ currentScrollLocation = tabForCoordinate(tabPane,
+ currentScrollOffset,
+ rects[index].y);
+ break;
+ default:
+ if ((diff = rects[index].y + rects[index].height
+ - decrButton.getY() - currentScrollOffset) > 0)
+ currentScrollOffset += diff;
+ else if ((diff = rects[index].y - currentScrollOffset) < 0)
+ {
+ if (index == 0)
+ currentScrollOffset = 0;
+ else
+ currentScrollOffset += diff;
+ }
+
+ currentScrollLocation = tabForCoordinate(tabPane,
+ rects[index].x,
+ currentScrollOffset);
+ }
+
+ updateViewPosition();
+ updateButtons();
+ }
+ }
+
+ /** Sets the enabled state of the increase and decrease button
+ * according to the current scrolling offset and tab pane width
+ * (or height in TOP/BOTTOM placement).
+ */
+ final void updateButtons()
+ {
+ int tc = tabPane.getTabCount();
+
+ // The increase button should be enabled as long as the
+ // right/bottom border of the last tab is under the left/top
+ // border of the decrease button.
+ switch (tabPane.getTabPlacement())
+ {
+ case JTabbedPane.BOTTOM:
+ case JTabbedPane.TOP:
+ incrButton.setEnabled(currentScrollLocation + 1 < tc
+ && rects[tc-1].x + rects[tc-1].width
+ - currentScrollOffset > decrButton.getX());
+ break;
+ default:
+ incrButton.setEnabled(currentScrollLocation + 1 < tc
+ && rects[tc-1].y + rects[tc-1].height
+ - currentScrollOffset > decrButton.getY());
+ }
+
+ // The decrease button is enabled when the tab pane is scrolled in any way.
+ decrButton.setEnabled(currentScrollOffset > 0);
+
+ }
/**
+ * Updates the position of the scrolling viewport's view
+ * according to the current scroll offset.
+ */
+ final void updateViewPosition()
+ {
+ Point p = viewport.getViewPosition();
+
+ switch (tabPane.getTabPlacement())
+ {
+ case JTabbedPane.LEFT:
+ case JTabbedPane.RIGHT:
+ p.y = currentScrollOffset;
+ break;
+ default:
+ p.x = currentScrollOffset;
+ }
+
+ viewport.setViewPosition(p);
+ }
+
+ /**
* This method creates a new BasicTabbedPaneUI.
*
* @param c The JComponent to create a UI for.
@@ -1585,22 +1971,30 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
return new TabbedPaneLayout();
else
{
+ runCount = 1;
+ tabRuns[0] = 0;
+
incrButton = createIncreaseButton();
+ incrButton.addMouseListener(mouseListener);
+
decrButton = createDecreaseButton();
- viewport = new ScrollingViewport();
- viewport.setLayout(null);
+ decrButton.addMouseListener(mouseListener);
+ decrButton.setEnabled(false);
+
panel = new ScrollingPanel();
+ panel.setSize(Integer.MAX_VALUE, Integer.MAX_VALUE);
+ panel.addMouseListener(mouseListener);
+ panel.addFocusListener(focusListener);
+
+ viewport = new ScrollingViewport();
+ viewport.setBackground(Color.LIGHT_GRAY);
viewport.setView(panel);
+ viewport.setLayout(null);
+
tabPane.add(incrButton);
tabPane.add(decrButton);
tabPane.add(viewport);
- currentScrollLocation = 0;
- decrButton.setEnabled(false);
- panel.addMouseListener(mouseListener);
- incrButton.addMouseListener(mouseListener);
- decrButton.addMouseListener(mouseListener);
- viewport.setBackground(Color.LIGHT_GRAY);
-
+
return new TabbedPaneScrollLayout();
}
}
@@ -1618,7 +2012,14 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
protected void uninstallComponents()
{
- // Nothing to be done.
+ if (incrButton != null)
+ tabPane.remove(incrButton);
+
+ if (decrButton != null)
+ tabPane.remove(decrButton);
+
+ if (viewport != null)
+ tabPane.remove(viewport);
}
/**
@@ -1631,8 +2032,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
"TabbedPane.font");
tabPane.setOpaque(false);
- highlight = UIManager.getColor("TabbedPane.highlight");
- lightHighlight = UIManager.getColor("TabbedPane.lightHighlight");
+ lightHighlight = UIManager.getColor("TabbedPane.highlight");
+ highlight = UIManager.getColor("TabbedPane.light");
shadow = UIManager.getColor("TabbedPane.shadow");
darkShadow = UIManager.getColor("TabbedPane.darkShadow");
@@ -1643,10 +2044,18 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
tabRunOverlay = UIManager.getInt("TabbedPane.tabRunOverlay");
tabInsets = UIManager.getInsets("TabbedPane.tabInsets");
- selectedTabPadInsets = UIManager.getInsets("TabbedPane.tabbedPaneTabPadInsets");
+ selectedTabPadInsets
+ = UIManager.getInsets("TabbedPane.selectedTabPadInsets");
tabAreaInsets = UIManager.getInsets("TabbedPane.tabAreaInsets");
- contentBorderInsets = UIManager.getInsets("TabbedPane.tabbedPaneContentBorderInsets");
+ contentBorderInsets
+ = UIManager.getInsets("TabbedPane.contentBorderInsets");
tabsOpaque = UIManager.getBoolean("TabbedPane.tabsOpaque");
+
+ // Although 'TabbedPane.contentAreaColor' is not defined in the defaults
+ // of BasicLookAndFeel it is used by this class.
+ selectedColor = UIManager.getColor("TabbedPane.contentAreaColor");
+ if (selectedColor == null)
+ selectedColor = UIManager.getColor("control");
calcRect = new Rectangle();
tabRuns = new int[10];
@@ -1663,6 +2072,9 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
tabAreaRect = null;
contentRect = null;
tabRuns = null;
+
+ tempIconRect = null;
+ tempTextRect = null;
contentBorderInsets = null;
tabAreaInsets = null;
@@ -1674,11 +2086,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
shadow = null;
lightHighlight = null;
highlight = null;
-
- // Install UI colors and fonts.
- LookAndFeel.installColorsAndFont(tabPane, "TabbedPane.background",
- "TabbedPane.foreground",
- "TabbedPane.font");
+
+ selectedColor = null;
}
/**
@@ -1706,6 +2115,18 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
tabPane.removePropertyChangeListener(propertyChangeListener);
tabPane.removeChangeListener(tabChangeListener);
tabPane.removeMouseListener(mouseListener);
+
+ if (incrButton != null)
+ incrButton.removeMouseListener(mouseListener);
+
+ if (decrButton != null)
+ decrButton.removeMouseListener(mouseListener);
+
+ if (panel != null)
+ {
+ panel.removeMouseListener(mouseListener);
+ panel.removeFocusListener(focusListener);
+ }
focusListener = null;
propertyChangeListener = null;
@@ -1757,18 +2178,31 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
* This method installs keyboard actions for the JTabbedPane.
*/
protected void installKeyboardActions()
- throws NotImplementedException
{
- // FIXME: Implement.
+ InputMap keyMap = (InputMap) UIManager.get("TabbedPane.focusInputMap");
+ SwingUtilities.replaceUIInputMap(tabPane, JComponent.WHEN_FOCUSED, keyMap);
+
+ keyMap = (InputMap) UIManager.get("TabbedPane.ancestorInputMap");
+ SwingUtilities
+ .replaceUIInputMap(tabPane,
+ JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
+ keyMap);
+
+ ActionMap map = getActionMap();
+ SwingUtilities.replaceUIActionMap(tabPane, map);
}
/**
* This method uninstalls keyboard actions for the JTabbedPane.
*/
protected void uninstallKeyboardActions()
- throws NotImplementedException
{
- // FIXME: Implement.
+ SwingUtilities.replaceUIActionMap(tabPane, null);
+ SwingUtilities.replaceUIInputMap(tabPane, JComponent.WHEN_FOCUSED, null);
+ SwingUtilities
+ .replaceUIInputMap(tabPane,
+ JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
+ null);
}
/**
@@ -1808,9 +2242,25 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
if (tabPane.getTabCount() == 0)
return;
+
+ int index = tabPane.getSelectedIndex();
+ if (index < 0)
+ index = 0;
+
+ int tabPlacement = tabPane.getTabPlacement();
+
+ // Paint the tab area only in WRAP_TAB_LAYOUT Mode from this method
+ // because it is done through the ScrollingViewport.paint() method
+ // for the SCROLL_TAB_LAYOUT mode.
if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT)
- paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex());
- paintContentBorder(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex());
+ {
+ g.setColor(highlight);
+ g.fillRect(tabAreaRect.x, tabAreaRect.y,
+ tabAreaRect.width, tabAreaRect.height);
+ paintTabArea(g, tabPlacement, index);
+ }
+
+ paintContentBorder(g, tabPlacement, index);
}
/**
@@ -1823,14 +2273,12 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex)
{
- Rectangle ir = new Rectangle();
- Rectangle tr = new Rectangle();
-
- boolean isScroll = tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT;
-
// Please note: the ordering of the painting is important.
// we WANT to paint the outermost run first and then work our way in.
+
+ // The following drawing code works for both tab layouts.
int tabCount = tabPane.getTabCount();
+
for (int i = runCount - 1; i >= 0; --i)
{
int start = tabRuns[i];
@@ -1844,14 +2292,16 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
{
if (j != selectedIndex)
{
- paintTab(g, tabPlacement, rects, j, ir, tr);
+ paintTab(g, tabPlacement, rects, j,
+ tempIconRect, tempTextRect);
}
}
}
-
+
// Paint selected tab in front of every other tab.
if (selectedIndex >= 0)
- paintTab(g, tabPlacement, rects, selectedIndex, ir, tr);
+ paintTab(g, tabPlacement, rects, selectedIndex,
+ tempIconRect, tempTextRect);
}
/**
@@ -1891,8 +2341,10 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
// Paint the text.
paintText(g, tabPlacement, tabPane.getFont(), fm, tabIndex, title,
textRect, isSelected);
+
// Paint icon if necessary.
paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected);
+
// Paint focus indicator.
paintFocusIndicator(g, tabPlacement, rects, tabIndex, iconRect, textRect,
isSelected);
@@ -2032,8 +2484,17 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
protected int getTabLabelShiftX(int tabPlacement, int tabIndex,
boolean isSelected)
{
- // No reason to shift.
- return 0;
+ switch (tabPlacement)
+ {
+ default:
+ case SwingUtilities.TOP:
+ case SwingUtilities.BOTTOM:
+ return 1;
+ case SwingUtilities.LEFT:
+ return (isSelected) ? -1 : 1;
+ case SwingUtilities.RIGHT:
+ return (isSelected) ? 1 : -1;
+ }
}
/**
@@ -2049,8 +2510,17 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
protected int getTabLabelShiftY(int tabPlacement, int tabIndex,
boolean isSelected)
{
- // No reason to shift.
- return 0;
+ switch (tabPlacement)
+ {
+ default:
+ case SwingUtilities.TOP:
+ return (isSelected) ? -1 : 1;
+ case SwingUtilities.BOTTOM:
+ return (isSelected) ? 1 : -1;
+ case SwingUtilities.LEFT:
+ case SwingUtilities.RIGHT:
+ return 0;
+ }
}
/**
@@ -2080,32 +2550,33 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
g.setColor(focus);
switch (tabPlacement)
- {
- case LEFT:
- x = rect.x + 3;
- y = rect.y + 3;
- w = rect.width - 5;
- h = rect.height - 6;
- break;
- case RIGHT:
- x = rect.x + 2;
- y = rect.y + 3;
- w = rect.width - 6;
- h = rect.height - 5;
- break;
- case BOTTOM:
- x = rect.x + 3;
- y = rect.y + 2;
- w = rect.width - 6;
- h = rect.height - 5;
- break;
- case TOP:
- default:
- x = rect.x + 3;
- y = rect.y + 3;
- w = rect.width - 6;
- h = rect.height - 5;
- }
+ {
+ case LEFT:
+ x = rect.x + 3;
+ y = rect.y + 3;
+ w = rect.width - 5;
+ h = rect.height - 6;
+ break;
+ case RIGHT:
+ x = rect.x + 2;
+ y = rect.y + 3;
+ w = rect.width - 6;
+ h = rect.height - 5;
+ break;
+ case BOTTOM:
+ x = rect.x + 3;
+ y = rect.y + 2;
+ w = rect.width - 6;
+ h = rect.height - 5;
+ break;
+ case TOP:
+ default:
+ x = rect.x + 3;
+ y = rect.y + 3;
+ w = rect.width - 6;
+ h = rect.height - 5;
+ }
+
BasicGraphicsUtils.drawDashedRect(g, x, y, w, h);
}
}
@@ -2127,34 +2598,109 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
{
Color saved = g.getColor();
- if (! isSelected || tabPlacement != SwingConstants.TOP)
- {
+ switch (tabPlacement)
+ {
+ case SwingConstants.TOP:
g.setColor(shadow);
- g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
- g.setColor(darkShadow);
- g.drawLine(x, y + h, x + w, y + h);
- }
+ // Inner right line.
+ g.drawLine(x + w - 2, y + 2, x + w - 2, y + h);
- if (! isSelected || tabPlacement != SwingConstants.LEFT)
- {
g.setColor(darkShadow);
- g.drawLine(x + w, y, x + w, y + h);
+ // Outer right line.
+ g.drawLine(x + w - 1, y + 2, x + w - 1, y + h);
+
+ // Upper right corner.
+ g.drawLine(x + w - 2, y + 1, x + w - 1, y + 2);
+
+ g.setColor(lightHighlight);
+
+ // Left line.
+ g.drawLine(x, y + 3, x, y + h);
+
+ // Upper line.
+ g.drawLine(x + 3, y, x + w - 3, y);
+
+ // Upper left corner.
+ g.drawLine(x, y + 2, x + 2, y);
+
+ break;
+ case SwingConstants.LEFT:
+ g.setColor(lightHighlight);
+ // Top line.
+ g.drawLine(x + 3, y, x + w - 1, y);
+
+ // Top left border.
+ g.drawLine(x + 2, y, x, y + 2);
+
+ // Left line.
+ g.drawLine(x, y + 3, x, y + h - 4);
+
+ // Bottom left corner.
+ g.drawLine(x, y + h - 3, x + 1, y + h - 2);
+
+ g.setColor(darkShadow);
+ // Outer bottom line.
+ g.drawLine(x + 2, y + h - 1, x + w - 1, y + h - 1);
+
g.setColor(shadow);
- g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
- }
+ // Inner bottom line.
+ g.drawLine(x + 2, y + h - 2, x + w - 1, y + h - 2);
+
+ break;
+ case SwingConstants.BOTTOM:
+ g.setColor(shadow);
+ // Inner right line.
+ g.drawLine(x + w - 2, y, x + w - 2, y + h - 2);
- if (! isSelected || tabPlacement != SwingConstants.RIGHT)
- {
- g.setColor(lightHighlight);
- g.drawLine(x, y, x, y + h);
- }
+ // Inner bottom line.
+ g.drawLine(x + 2, y + h - 1, x + w - 3, y + h - 1);
- if (! isSelected || tabPlacement != SwingConstants.BOTTOM)
- {
+ g.setColor(darkShadow);
+ // Outer right line.
+ g.drawLine(x + w - 1, y, x + w - 1, y + h - 3);
+
+ // Bottom right corner.
+ g.drawLine(x + w - 1, y + h - 2, x + w - 3, y + h);
+
+ // Bottom line.
+ g.drawLine(x + 2, y + h, x + w - 4, y + h);
+
g.setColor(lightHighlight);
- g.drawLine(x, y, x + w, y);
- }
-
+ // Left line.
+ g.drawLine(x, y, x, y + h - 3);
+
+ // Bottom left corner.
+ g.drawLine(x, y + h - 2, x + 1, y + h - 1);
+ break;
+ case SwingConstants.RIGHT:
+ g.setColor(lightHighlight);
+ // Top line.
+ g.drawLine(x, y, x + w - 3, y);
+
+ g.setColor(darkShadow);
+ // Top right corner.
+ g.drawLine(x + w - 2, y + 1, x + w - 1, y + 2);
+
+ // Outer right line.
+ g.drawLine(x + w - 1, y + 3, x + w - 1, y + h - 3);
+
+ // Bottom right corner.
+ g.drawLine(x + w - 2, y + h - 2, x + w - 3, y + h - 1);
+
+ // Bottom line.
+ g.drawLine(x, y + h - 1, x + w - 4, y + h - 1);
+
+ g.setColor(shadow);
+
+ // Inner right line.
+ g.drawLine(x + w - 2, y + 2, x + w - 2, y + h - 3);
+
+ // Inner bottom line.
+ g.drawLine(x, y + h - 2, x + w - 3, y + h - 2);
+
+ break;
+ }
+
g.setColor(saved);
}
@@ -2175,17 +2721,32 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
boolean isSelected)
{
Color saved = g.getColor();
+
if (isSelected)
- g.setColor(Color.LIGHT_GRAY);
+ g.setColor(selectedColor);
else
{
Color bg = tabPane.getBackgroundAt(tabIndex);
if (bg == null)
- bg = Color.GRAY;
+ bg = Color.LIGHT_GRAY;
g.setColor(bg);
}
- g.fillRect(x, y, w, h);
+ switch (tabPlacement)
+ {
+ case SwingConstants.TOP:
+ g.fillRect(x + 1, y + 1, w - 1, h - 1);
+ break;
+ case SwingConstants.BOTTOM:
+ g.fillRect(x, y, w - 1, h - 1);
+ break;
+ case SwingConstants.LEFT:
+ g.fillRect(x + 1, y + 1, w - 1, h - 2);
+ break;
+ case SwingConstants.RIGHT:
+ g.fillRect(x, y + 1, w - 1, h - 2);
+ break;
+ }
g.setColor(saved);
}
@@ -2262,25 +2823,27 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
Color saved = g.getColor();
g.setColor(lightHighlight);
- int startgap = rects[selectedIndex].x;
- int endgap = rects[selectedIndex].x + rects[selectedIndex].width;
-
- int diff = 0;
+ int startgap = rects[selectedIndex].x - currentScrollOffset;
+ int endgap = rects[selectedIndex].x + rects[selectedIndex].width
+ - currentScrollOffset;
- if (tabPlacement == SwingConstants.TOP)
+ // Paint the highlight line with a gap if the tabs are at the top
+ // and the selected tab is inside the visible area.
+ if (tabPlacement == SwingConstants.TOP && startgap >= 0)
{
- if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
- {
- Point p = findPointForIndex(currentScrollLocation);
- diff = p.x;
- }
-
- g.drawLine(x, y, startgap - diff, y);
- g.drawLine(endgap - diff, y, x + w, y);
+ g.drawLine(x, y, startgap, y);
+ g.drawLine(endgap, y, x + w - 1, y);
+
+ g.setColor(selectedColor);
+ g.drawLine(startgap, y, endgap - 1, y);
}
else
g.drawLine(x, y, x + w, y);
-
+
+ g.setColor(selectedColor);
+ g.drawLine(x, y + 1, x + w - 1, y + 1);
+ g.drawLine(x, y + 2, x + w - 1, y + 2);
+
g.setColor(saved);
}
@@ -2302,24 +2865,25 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
Color saved = g.getColor();
g.setColor(lightHighlight);
- int startgap = rects[selectedIndex].y;
- int endgap = rects[selectedIndex].y + rects[selectedIndex].height;
+ int startgap = rects[selectedIndex].y - currentScrollOffset;
+ int endgap = rects[selectedIndex].y + rects[selectedIndex].height
+ - currentScrollOffset;
int diff = 0;
- if (tabPlacement == SwingConstants.LEFT)
+ if (tabPlacement == SwingConstants.LEFT && startgap >= 0)
{
- if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
- {
- Point p = findPointForIndex(currentScrollLocation);
- diff = p.y;
- }
-
- g.drawLine(x, y, x, startgap - diff);
- g.drawLine(x, endgap - diff, x, y + h);
+ g.drawLine(x, y, x, startgap);
+ g.drawLine(x, endgap, x, y + h - 1);
+
+ g.setColor(selectedColor);
+ g.drawLine(x, startgap, x, endgap - 1);
}
else
- g.drawLine(x, y, x, y + h);
+ g.drawLine(x, y, x, y + h - 1);
+
+ g.setColor(selectedColor);
+ g.drawLine(x + 1, y + 1, x + 1, y + h - 4);
g.setColor(saved);
}
@@ -2341,34 +2905,34 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
{
Color saved = g.getColor();
- int startgap = rects[selectedIndex].x;
- int endgap = rects[selectedIndex].x + rects[selectedIndex].width;
-
- int diff = 0;
+ int startgap = rects[selectedIndex].x - currentScrollOffset;
+ int endgap = rects[selectedIndex].x + rects[selectedIndex].width
+ - currentScrollOffset;
- if (tabPlacement == SwingConstants.BOTTOM)
+ if (tabPlacement == SwingConstants.BOTTOM && startgap >= 0)
{
- if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
- {
- Point p = findPointForIndex(currentScrollLocation);
- diff = p.x;
- }
-
g.setColor(shadow);
- g.drawLine(x + 1, y + h - 1, startgap - diff, y + h - 1);
- g.drawLine(endgap - diff, y + h - 1, x + w - 1, y + h - 1);
+ g.drawLine(x + 1, y + h - 2, startgap, y + h - 2);
+ g.drawLine(endgap, y + h - 2, x + w - 2, y + h - 2);
g.setColor(darkShadow);
- g.drawLine(x, y + h, startgap - diff, y + h);
- g.drawLine(endgap - diff, y + h, x + w, y + h);
+ g.drawLine(x, y + h - 1, startgap , y + h - 1);
+ g.drawLine(endgap, y + h - 1, x + w - 1, y + h - 1);
+
+ g.setColor(selectedColor);
+ g.drawLine(startgap, y + h - 1, endgap - 1, y + h - 1);
+ g.drawLine(startgap, y + h - 2, endgap - 1, y + h - 2);
}
else
{
g.setColor(shadow);
- g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
+ g.drawLine(x + 1, y + h - 2, x + w - 1, y + h - 2);
g.setColor(darkShadow);
- g.drawLine(x, y + h, x + w, y + h);
+ g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
}
+
+ g.setColor(selectedColor);
+ g.drawLine(x + 1, y + h - 3, x + w - 2, y + h - 3);
g.setColor(saved);
}
@@ -2389,34 +2953,36 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
int w, int h)
{
Color saved = g.getColor();
- int startgap = rects[selectedIndex].y;
- int endgap = rects[selectedIndex].y + rects[selectedIndex].height;
+ int startgap = rects[selectedIndex].y - currentScrollOffset;
+ int endgap = rects[selectedIndex].y + rects[selectedIndex].height
+ - currentScrollOffset;
int diff = 0;
- if (tabPlacement == SwingConstants.RIGHT)
+ if (tabPlacement == SwingConstants.RIGHT && startgap >= 0)
{
- if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
- {
- Point p = findPointForIndex(currentScrollLocation);
- diff = p.y;
- }
-
g.setColor(shadow);
- g.drawLine(x + w - 1, y + 1, x + w - 1, startgap - diff);
- g.drawLine(x + w - 1, endgap - diff, x + w - 1, y + h - 1);
+ g.drawLine(x + w - 2, y + 1, x + w - 2, startgap);
+ g.drawLine(x + w - 2, endgap, x + w - 2, y + h - 2);
g.setColor(darkShadow);
- g.drawLine(x + w, y, x + w, startgap - diff);
- g.drawLine(x + w, endgap - diff, x + w, y + h);
+ g.drawLine(x + w - 1, y, x + w - 1, startgap);
+ g.drawLine(x + w - 1, endgap, x + w - 1, y + h - 2);
+
+ g.setColor(selectedColor);
+ g.drawLine(x + w - 2, startgap, x + w - 2, endgap - 1);
+ g.drawLine(x + w - 1, startgap, x + w - 1, endgap - 1);
}
else
{
g.setColor(shadow);
- g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
+ g.drawLine(x + w - 2, y + 1, x + w - 2, y + h - 2);
g.setColor(darkShadow);
- g.drawLine(x + w, y, x + w, y + h);
+ g.drawLine(x + w - 1, y, x + w - 1, y + h - 2);
}
+
+ g.setColor(selectedColor);
+ g.drawLine(x + w - 3, y + 1, x + w - 3, y + h - 4);
g.setColor(saved);
}
@@ -2460,11 +3026,15 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
public int tabForCoordinate(JTabbedPane pane, int x, int y)
{
+ // Note: This code is tab layout mode agnostic.
if (! tabPane.isValid())
tabPane.validate();
-
+
int tabCount = tabPane.getTabCount();
- int index = -1;
+
+ // If the user clicked outside of any tab rect the
+ // selection should not change.
+ int index = tabPane.getSelectedIndex();
for (int i = 0; i < tabCount; ++i)
{
if (rects[i].contains(x, y))
@@ -2474,8 +3044,6 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
}
}
- // FIXME: Handle scrollable tab layout.
-
return index;
}
@@ -2571,7 +3139,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
protected int getRunForTab(int tabCount, int tabIndex)
{
if (runCount == 1 && tabIndex < tabCount && tabIndex >= 0)
- return 1;
+ return 0;
for (int i = 0; i < runCount; i++)
{
int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1;
@@ -2690,6 +3258,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
protected View getTextViewForTab(int tabIndex)
{
+ // FIXME: When the label contains HTML this should return something
+ // non-null.
return null;
}
@@ -2706,7 +3276,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
protected int calculateTabHeight(int tabPlacement, int tabIndex,
int fontHeight)
{
- // FIXME: Handle HTML somehow.
+ // FIXME: Handle HTML by using the view (see getTextViewForTab).
int height = fontHeight;
Icon icon = getIconForTab(tabIndex);
@@ -2923,8 +3493,9 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
{
int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(),
tabPane.getSelectedIndex(),
- (tabPlacement == SwingConstants.RIGHT)
- ? true : false);
+ (tabPlacement == SwingConstants.TOP)
+ ? direction == SwingConstants.NORTH
+ : direction == SwingConstants.SOUTH);
selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(),
offset);
}
@@ -2940,8 +3511,9 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
{
int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(),
tabPane.getSelectedIndex(),
- (tabPlacement == SwingConstants.RIGHT)
- ? true : false);
+ (tabPlacement == SwingConstants.LEFT)
+ ? direction == SwingConstants.WEST
+ : direction == SwingConstants.EAST);
selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(),
offset);
}
@@ -2955,8 +3527,13 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
protected void selectNextTabInRun(int current)
{
- tabPane.setSelectedIndex(getNextTabIndexInRun(tabPane.getTabCount(),
- current));
+ current = getNextTabIndexInRun(tabPane.getTabCount(),
+ current);
+
+ if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
+ scrollTab(current, tabPane.getTabPlacement());
+
+ tabPane.setSelectedIndex(current);
}
/**
@@ -2966,8 +3543,13 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
protected void selectPreviousTabInRun(int current)
{
- tabPane.setSelectedIndex(getPreviousTabIndexInRun(tabPane.getTabCount(),
- current));
+ current = getPreviousTabIndexInRun(tabPane.getTabCount(),
+ current);
+
+ if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
+ scrollTab(current, tabPane.getTabPlacement());
+
+ tabPane.setSelectedIndex(current);
}
/**
@@ -2977,7 +3559,12 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
protected void selectNextTab(int current)
{
- tabPane.setSelectedIndex(getNextTabIndex(current));
+ current = getNextTabIndex(current);
+
+ if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
+ scrollTab(current, tabPane.getTabPlacement());
+
+ tabPane.setSelectedIndex(current);
}
/**
@@ -2987,7 +3574,12 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
*/
protected void selectPreviousTab(int current)
{
- tabPane.setSelectedIndex(getPreviousTabIndex(current));
+ current = getPreviousTabIndex(current);
+
+ if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
+ scrollTab(current, tabPane.getTabPlacement());
+
+ tabPane.setSelectedIndex(current);
}
/**
@@ -3021,7 +3613,11 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
int index = tabForCoordinate(tabPane, x, y);
if (index != -1)
- tabPane.setSelectedIndex(index);
+ {
+ if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT)
+ scrollTab(index, tabPlacement);
+ tabPane.setSelectedIndex(index);
+ }
}
// This method is called when you press up/down to cycle through tab runs.
@@ -3058,6 +3654,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
else
offset = rects[lastTabInRun(tabCount, nextRun)].x
- rects[lastTabInRun(tabCount, currRun)].x;
+
return offset;
}
@@ -3104,9 +3701,12 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
{
int index = getNextTabIndex(base);
int run = getRunForTab(tabCount, base);
- if (index == lastTabInRun(tabCount, run) + 1)
- index = lastTabInRun(tabCount, getPreviousTabRun(run)) + 1;
- return getNextTabIndex(base);
+ if (base == lastTabInRun(tabCount, run))
+ index = (run > 0)
+ ? lastTabInRun(tabCount, getPreviousTabRun(run)) + 1
+ : 0;
+
+ return index;
}
/**
@@ -3124,7 +3724,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
int run = getRunForTab(tabCount, base);
if (index == lastTabInRun(tabCount, getPreviousTabRun(run)))
index = lastTabInRun(tabCount, run);
- return getPreviousTabIndex(base);
+
+ return index;
}
/**
@@ -3182,6 +3783,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
// so I won't check it either.
switch (targetPlacement)
{
+ default:
case SwingConstants.TOP:
targetInsets.top = topInsets.top;
targetInsets.left = topInsets.left;
@@ -3208,6 +3810,44 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants
break;
}
}
+
+ ActionMap getActionMap()
+ {
+ ActionMap map = (ActionMap) UIManager.get("TabbedPane.actionMap");
+
+ if (map == null) // first time here
+ {
+ map = createActionMap();
+ if (map != null)
+ UIManager.put("TabbedPane.actionMap", map);
+ }
+ return map;
+ }
+
+ ActionMap createActionMap()
+ {
+ ActionMap map = new ActionMapUIResource();
+
+ map.put("navigatePageDown", new NavigatePageDownAction());
+ map.put("navigatePageUp", new NavigatePageUpAction());
+ map.put("navigateDown",
+ new NavigateAction("navigateDown", SwingConstants.SOUTH));
+
+ map.put("navigateUp",
+ new NavigateAction("navigateUp", SwingConstants.NORTH));
+
+ map.put("navigateLeft",
+ new NavigateAction("navigateLeft", SwingConstants.WEST));
+
+ map.put("navigateRight",
+ new NavigateAction("navigateRight", SwingConstants.EAST));
+
+ map.put("requestFocusForVisibleComponent",
+ new RequestFocusForVisibleComponentAction());
+ map.put("requestFocus", new RequestFocusAction());
+
+ return map;
+ }
/**
* Sets the tab which should be highlighted when in rollover mode. And
diff --git a/javax/swing/plaf/basic/BasicTableUI.java b/javax/swing/plaf/basic/BasicTableUI.java
index 85c6b574d..15be4d57e 100644
--- a/javax/swing/plaf/basic/BasicTableUI.java
+++ b/javax/swing/plaf/basic/BasicTableUI.java
@@ -38,8 +38,6 @@ exception statement from your version. */
package javax.swing.plaf.basic;
-import gnu.classpath.NotImplementedException;
-
import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
@@ -48,7 +46,6 @@ import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
@@ -58,6 +55,7 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.AbstractAction;
+import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.CellRendererPane;
import javax.swing.DefaultCellEditor;
@@ -65,16 +63,16 @@ import javax.swing.DefaultListSelectionModel;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JTable;
-import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.LookAndFeel;
+import javax.swing.SwingUtilities;
+import javax.swing.TransferHandler;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
-import javax.swing.plaf.InputMapUIResource;
import javax.swing.plaf.TableUI;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
@@ -164,14 +162,37 @@ public class BasicTableUI extends TableUI
public class FocusHandler implements FocusListener
{
- public void focusGained(FocusEvent e) throws NotImplementedException
+ public void focusGained(FocusEvent e)
{
- // TODO: Implement this properly.
+ // The only thing that is affected by a focus change seems to be
+ // how the lead cell is painted. So we repaint this cell.
+ repaintLeadCell();
}
- public void focusLost(FocusEvent e) throws NotImplementedException
+ public void focusLost(FocusEvent e)
+ {
+ // The only thing that is affected by a focus change seems to be
+ // how the lead cell is painted. So we repaint this cell.
+ repaintLeadCell();
+ }
+
+ /**
+ * Repaints the lead cell in response to a focus change, to refresh
+ * the display of the focus indicator.
+ */
+ private void repaintLeadCell()
{
- // TODO: Implement this properly.
+ int rowCount = table.getRowCount();
+ int columnCount = table.getColumnCount();
+ int rowLead = table.getSelectionModel().getLeadSelectionIndex();
+ int columnLead = table.getColumnModel().getSelectionModel().
+ getLeadSelectionIndex();
+ if (rowLead >= 0 && rowLead < rowCount && columnLead >= 0
+ && columnLead < columnCount)
+ {
+ Rectangle dirtyRect = table.getCellRect(rowLead, columnLead, false);
+ table.repaint(dirtyRect);
+ }
}
}
@@ -242,20 +263,19 @@ public class BasicTableUI extends TableUI
}
}
- public void mouseEntered(MouseEvent e)
- throws NotImplementedException
+ public void mouseEntered(MouseEvent e)
{
- // TODO: What should be done here, if anything?
+ // Nothing to do here.
}
- public void mouseExited(MouseEvent e) throws NotImplementedException
+ public void mouseExited(MouseEvent e)
{
- // TODO: What should be done here, if anything?
+ // Nothing to do here.
}
- public void mouseMoved(MouseEvent e) throws NotImplementedException
+ public void mouseMoved(MouseEvent e)
{
- // TODO: What should be done here, if anything?
+ // Nothing to do here.
}
public void mousePressed(MouseEvent e)
@@ -288,6 +308,9 @@ public class BasicTableUI extends TableUI
colLead != colModel.getLeadSelectionIndex())
if (table.isEditing())
table.editingStopped(new ChangeEvent(e));
+
+ // Must request focus explicitly.
+ table.requestFocusInWindow();
}
}
@@ -457,66 +480,100 @@ public class BasicTableUI extends TableUI
table.setOpaque(true);
}
+ /**
+ * Installs keyboard actions on the table.
+ */
protected void installKeyboardActions()
{
- InputMap ancestorMap = (InputMap) UIManager.get("Table.ancestorInputMap");
- InputMapUIResource parentInputMap = new InputMapUIResource();
- // FIXME: The JDK uses a LazyActionMap for parentActionMap
- ActionMap parentActionMap = new ActionMapUIResource();
- action = new TableAction();
- Object keys[] = ancestorMap.allKeys();
- // Register key bindings in the UI InputMap-ActionMap pair
- for (int i = 0; i < keys.length; i++)
- {
- KeyStroke stroke = (KeyStroke) keys[i];
- String actionString = (String) ancestorMap.get(stroke);
+ // Install the input map.
+ InputMap inputMap =
+ (InputMap) SharedUIDefaults.get("Table.ancestorInputMap");
+ SwingUtilities.replaceUIInputMap(table,
+ JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
+ inputMap);
- parentInputMap.put(KeyStroke.getKeyStroke(stroke.getKeyCode(),
- stroke.getModifiers()),
- actionString);
-
- parentActionMap.put(actionString,
- new ActionListenerProxy(action, actionString));
+ // FIXME: The JDK uses a LazyActionMap for parentActionMap
+ SwingUtilities.replaceUIActionMap(table, getActionMap());
- }
- // Set the UI InputMap-ActionMap pair to be the parents of the
- // JTable's InputMap-ActionMap pair
- parentInputMap.setParent(table.getInputMap(
- JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).getParent());
- parentActionMap.setParent(table.getActionMap().getParent());
- table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).
- setParent(parentInputMap);
- table.getActionMap().setParent(parentActionMap);
}
/**
- * This class is used to mimmic the behaviour of the JDK when registering
- * keyboard actions. It is the same as the private class used in JComponent
- * for the same reason. This class receives an action event and dispatches
- * it to the true receiver after altering the actionCommand property of the
- * event.
+ * Fetches the action map from the UI defaults, or create a new one
+ * if the action map hasn't been initialized.
+ *
+ * @return the action map
*/
- private static class ActionListenerProxy
- extends AbstractAction
+ private ActionMap getActionMap()
{
- ActionListener target;
- String bindingCommandName;
-
- public ActionListenerProxy(ActionListener li,
- String cmd)
- {
- target = li;
- bindingCommandName = cmd;
- }
+ ActionMap am = (ActionMap) UIManager.get("Table.actionMap");
+ if (am == null)
+ {
+ am = createDefaultActions();
+ UIManager.getLookAndFeelDefaults().put("Table.actionMap", am);
+ }
+ return am;
+ }
- public void actionPerformed(ActionEvent e)
- {
- ActionEvent derivedEvent = new ActionEvent(e.getSource(),
- e.getID(),
- bindingCommandName,
- e.getModifiers());
- target.actionPerformed(derivedEvent);
- }
+ private ActionMap createDefaultActions()
+ {
+ ActionMapUIResource am = new ActionMapUIResource();
+ Action action = new TableAction();
+
+ am.put("cut", TransferHandler.getCutAction());
+ am.put("copy", TransferHandler.getCopyAction());
+ am.put("paste", TransferHandler.getPasteAction());
+
+ am.put("cancel", action);
+ am.put("selectAll", action);
+ am.put("clearSelection", action);
+ am.put("startEditing", action);
+
+ am.put("selectNextRow", action);
+ am.put("selectNextRowCell", action);
+ am.put("selectNextRowExtendSelection", action);
+ am.put("selectNextRowChangeLead", action);
+
+ am.put("selectPreviousRow", action);
+ am.put("selectPreviousRowCell", action);
+ am.put("selectPreviousRowExtendSelection", action);
+ am.put("selectPreviousRowChangeLead", action);
+
+ am.put("selectNextColumn", action);
+ am.put("selectNextColumnCell", action);
+ am.put("selectNextColumnExtendSelection", action);
+ am.put("selectNextColumnChangeLead", action);
+
+ am.put("selectPreviousColumn", action);
+ am.put("selectPreviousColumnCell", action);
+ am.put("selectPreviousColumnExtendSelection", action);
+ am.put("selectPreviousColumnChangeLead", action);
+
+ am.put("scrollLeftChangeSelection", action);
+ am.put("scrollLeftExtendSelection", action);
+ am.put("scrollRightChangeSelection", action);
+ am.put("scrollRightExtendSelection", action);
+
+ am.put("scrollUpChangeSelection", action);
+ am.put("scrollUpExtendSelection", action);
+ am.put("scrollDownChangeSelection", action);
+ am.put("scrolldownExtendSelection", action);
+
+ am.put("selectFirstColumn", action);
+ am.put("selectFirstColumnExtendSelection", action);
+ am.put("selectLastColumn", action);
+ am.put("selectLastColumnExtendSelection", action);
+
+ am.put("selectFirstRow", action);
+ am.put("selectFirstRowExtendSelection", action);
+ am.put("selectLastRow", action);
+ am.put("selectLastRowExtendSelection", action);
+
+ am.put("addToSelection", action);
+ am.put("toggleAndAnchor", action);
+ am.put("extendTo", action);
+ am.put("moveSelectionTo", action);
+
+ return am;
}
/**
@@ -525,7 +582,8 @@ public class BasicTableUI extends TableUI
* method is called when a key that has been registered for the JTable
* is received.
*/
- class TableAction extends AbstractAction
+ private static class TableAction
+ extends AbstractAction
{
/**
* What to do when this action is called.
@@ -534,6 +592,8 @@ public class BasicTableUI extends TableUI
*/
public void actionPerformed(ActionEvent e)
{
+ JTable table = (JTable) e.getSource();
+
DefaultListSelectionModel rowModel
= (DefaultListSelectionModel) table.getSelectionModel();
DefaultListSelectionModel colModel
@@ -544,9 +604,11 @@ public class BasicTableUI extends TableUI
int colLead = colModel.getLeadSelectionIndex();
int colMax = table.getModel().getColumnCount() - 1;
-
- String command = e.getActionCommand();
-
+
+ // The command with which the action has been called is stored
+ // in this undocumented action value. This allows us to have only
+ // one Action instance to serve all keyboard input for JTable.
+ String command = (String) getValue("__command__");
if (command.equals("selectPreviousRowExtendSelection"))
{
rowModel.setLeadSelectionIndex(Math.max(rowLead - 1, 0));
@@ -604,11 +666,11 @@ public class BasicTableUI extends TableUI
else if (command.equals("scrollUpExtendSelection"))
{
int target;
- if (rowLead == getFirstVisibleRowIndex())
- target = Math.max(0, rowLead - (getLastVisibleRowIndex()
- - getFirstVisibleRowIndex() + 1));
+ if (rowLead == getFirstVisibleRowIndex(table))
+ target = Math.max(0, rowLead - (getLastVisibleRowIndex(table)
+ - getFirstVisibleRowIndex(table) + 1));
else
- target = getFirstVisibleRowIndex();
+ target = getFirstVisibleRowIndex(table);
rowModel.setLeadSelectionIndex(target);
colModel.setLeadSelectionIndex(colLead);
@@ -621,11 +683,12 @@ public class BasicTableUI extends TableUI
else if (command.equals("scrollRightChangeSelection"))
{
int target;
- if (colLead == getLastVisibleColumnIndex())
- target = Math.min(colMax, colLead + (getLastVisibleColumnIndex()
- - getFirstVisibleColumnIndex() + 1));
+ if (colLead == getLastVisibleColumnIndex(table))
+ target = Math.min(colMax, colLead
+ + (getLastVisibleColumnIndex(table)
+ - getFirstVisibleColumnIndex(table) + 1));
else
- target = getLastVisibleColumnIndex();
+ target = getLastVisibleColumnIndex(table);
colModel.setSelectionInterval(target, target);
rowModel.setSelectionInterval(rowLead, rowLead);
@@ -638,11 +701,11 @@ public class BasicTableUI extends TableUI
else if (command.equals("scrollLeftChangeSelection"))
{
int target;
- if (colLead == getFirstVisibleColumnIndex())
- target = Math.max(0, colLead - (getLastVisibleColumnIndex()
- - getFirstVisibleColumnIndex() + 1));
+ if (colLead == getFirstVisibleColumnIndex(table))
+ target = Math.max(0, colLead - (getLastVisibleColumnIndex(table)
+ - getFirstVisibleColumnIndex(table) + 1));
else
- target = getFirstVisibleColumnIndex();
+ target = getFirstVisibleColumnIndex(table);
colModel.setSelectionInterval(target, target);
rowModel.setSelectionInterval(rowLead, rowLead);
@@ -724,14 +787,18 @@ public class BasicTableUI extends TableUI
// If there are multiple rows and columns selected, select the next
// cell and wrap at the edges of the selection.
if (command.indexOf("Column") != -1)
- advanceMultipleSelection(colModel, colMinSelected, colMaxSelected,
- rowModel, rowMinSelected, rowMaxSelected,
- command.equals("selectPreviousColumnCell"), true);
+ advanceMultipleSelection(table, colModel, colMinSelected,
+ colMaxSelected, rowModel, rowMinSelected,
+ rowMaxSelected,
+ command.equals("selectPreviousColumnCell"),
+ true);
else
- advanceMultipleSelection(rowModel, rowMinSelected, rowMaxSelected,
- colModel, colMinSelected, colMaxSelected,
- command.equals("selectPreviousRowCell"), false);
+ advanceMultipleSelection(table, rowModel, rowMinSelected,
+ rowMaxSelected, colModel, colMinSelected,
+ colMaxSelected,
+ command.equals("selectPreviousRowCell"),
+ false);
}
else if (command.equals("selectNextColumn"))
{
@@ -741,11 +808,11 @@ public class BasicTableUI extends TableUI
else if (command.equals("scrollLeftExtendSelection"))
{
int target;
- if (colLead == getFirstVisibleColumnIndex())
- target = Math.max(0, colLead - (getLastVisibleColumnIndex()
- - getFirstVisibleColumnIndex() + 1));
+ if (colLead == getFirstVisibleColumnIndex(table))
+ target = Math.max(0, colLead - (getLastVisibleColumnIndex(table)
+ - getFirstVisibleColumnIndex(table) + 1));
else
- target = getFirstVisibleColumnIndex();
+ target = getFirstVisibleColumnIndex(table);
colModel.setLeadSelectionIndex(target);
rowModel.setLeadSelectionIndex(rowLead);
@@ -753,11 +820,11 @@ public class BasicTableUI extends TableUI
else if (command.equals("scrollDownChangeSelection"))
{
int target;
- if (rowLead == getLastVisibleRowIndex())
- target = Math.min(rowMax, rowLead + (getLastVisibleRowIndex()
- - getFirstVisibleRowIndex() + 1));
+ if (rowLead == getLastVisibleRowIndex(table))
+ target = Math.min(rowMax, rowLead + (getLastVisibleRowIndex(table)
+ - getFirstVisibleRowIndex(table) + 1));
else
- target = getLastVisibleRowIndex();
+ target = getLastVisibleRowIndex(table);
rowModel.setSelectionInterval(target, target);
colModel.setSelectionInterval(colLead, colLead);
@@ -765,11 +832,11 @@ public class BasicTableUI extends TableUI
else if (command.equals("scrollRightExtendSelection"))
{
int target;
- if (colLead == getLastVisibleColumnIndex())
- target = Math.min(colMax, colLead + (getLastVisibleColumnIndex()
- - getFirstVisibleColumnIndex() + 1));
+ if (colLead == getLastVisibleColumnIndex(table))
+ target = Math.min(colMax, colLead + (getLastVisibleColumnIndex(table)
+ - getFirstVisibleColumnIndex(table) + 1));
else
- target = getLastVisibleColumnIndex();
+ target = getLastVisibleColumnIndex(table);
colModel.setLeadSelectionIndex(target);
rowModel.setLeadSelectionIndex(rowLead);
@@ -786,11 +853,11 @@ public class BasicTableUI extends TableUI
else if (command.equals("scrollDownExtendSelection"))
{
int target;
- if (rowLead == getLastVisibleRowIndex())
- target = Math.min(rowMax, rowLead + (getLastVisibleRowIndex()
- - getFirstVisibleRowIndex() + 1));
+ if (rowLead == getLastVisibleRowIndex(table))
+ target = Math.min(rowMax, rowLead + (getLastVisibleRowIndex(table)
+ - getFirstVisibleRowIndex(table) + 1));
else
- target = getLastVisibleRowIndex();
+ target = getLastVisibleRowIndex(table);
rowModel.setLeadSelectionIndex(target);
colModel.setLeadSelectionIndex(colLead);
@@ -798,11 +865,11 @@ public class BasicTableUI extends TableUI
else if (command.equals("scrollUpChangeSelection"))
{
int target;
- if (rowLead == getFirstVisibleRowIndex())
- target = Math.max(0, rowLead - (getLastVisibleRowIndex()
- - getFirstVisibleRowIndex() + 1));
+ if (rowLead == getFirstVisibleRowIndex(table))
+ target = Math.max(0, rowLead - (getLastVisibleRowIndex(table)
+ - getFirstVisibleRowIndex(table) + 1));
else
- target = getFirstVisibleRowIndex();
+ target = getFirstVisibleRowIndex(table);
rowModel.setSelectionInterval(target, target);
colModel.setSelectionInterval(colLead, colLead);
@@ -927,7 +994,7 @@ public class BasicTableUI extends TableUI
* Returns the column index of the first visible column.
* @return the column index of the first visible column.
*/
- int getFirstVisibleColumnIndex()
+ int getFirstVisibleColumnIndex(JTable table)
{
ComponentOrientation or = table.getComponentOrientation();
Rectangle r = table.getVisibleRect();
@@ -940,7 +1007,7 @@ public class BasicTableUI extends TableUI
* Returns the column index of the last visible column.
*
*/
- int getLastVisibleColumnIndex()
+ int getLastVisibleColumnIndex(JTable table)
{
ComponentOrientation or = table.getComponentOrientation();
Rectangle r = table.getVisibleRect();
@@ -953,7 +1020,7 @@ public class BasicTableUI extends TableUI
* Returns the row index of the first visible row.
*
*/
- int getFirstVisibleRowIndex()
+ int getFirstVisibleRowIndex(JTable table)
{
ComponentOrientation or = table.getComponentOrientation();
Rectangle r = table.getVisibleRect();
@@ -966,7 +1033,7 @@ public class BasicTableUI extends TableUI
* Returns the row index of the last visible row.
*
*/
- int getLastVisibleRowIndex()
+ int getLastVisibleRowIndex(JTable table)
{
ComponentOrientation or = table.getComponentOrientation();
Rectangle r = table.getVisibleRect();
@@ -978,7 +1045,7 @@ public class BasicTableUI extends TableUI
// area is larger than the table)
if (table.rowAtPoint(r.getLocation()) == -1)
{
- if (getFirstVisibleRowIndex() == -1)
+ if (getFirstVisibleRowIndex(table) == -1)
return -1;
else
return table.getModel().getRowCount() - 1;
@@ -1004,7 +1071,8 @@ public class BasicTableUI extends TableUI
* @param reverse true if shift was held for the event
* @param eventIsTab true if TAB was pressed, false if ENTER pressed
*/
- void advanceMultipleSelection(ListSelectionModel firstModel, int firstMin,
+ void advanceMultipleSelection(JTable table, ListSelectionModel firstModel,
+ int firstMin,
int firstMax, ListSelectionModel secondModel,
int secondMin, int secondMax, boolean reverse,
boolean eventIsTab)
@@ -1168,29 +1236,24 @@ public class BasicTableUI extends TableUI
table.addPropertyChangeListener(propertyChangeListener);
}
- protected void uninstallDefaults() throws NotImplementedException
+ /**
+ * Uninstalls UI defaults that have been installed by
+ * {@link #installDefaults()}.
+ */
+ protected void uninstallDefaults()
{
- // TODO: this method used to do the following which is not
- // quite right (at least it breaks apps that run fine with the
- // JDK):
- //
- // table.setFont(null);
- // table.setGridColor(null);
- // table.setForeground(null);
- // table.setBackground(null);
- // table.setSelectionForeground(null);
- // table.setSelectionBackground(null);
- //
- // This would leave the component in a corrupt state, which is
- // not acceptable. A possible solution would be to have component
- // level defaults installed, that get overridden by the UI defaults
- // and get restored in this method. I am not quite sure about this
- // though. / Roman Kennke
+ // Nothing to do here for now.
}
- protected void uninstallKeyboardActions() throws NotImplementedException
+ /**
+ * Uninstalls the keyboard actions that have been installed by
+ * {@link #installKeyboardActions()}.
+ */
+ protected void uninstallKeyboardActions()
{
- // TODO: Implement this properly.
+ SwingUtilities.replaceUIInputMap(table, JComponent.
+ WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);
+ SwingUtilities.replaceUIActionMap(table, null);
}
protected void uninstallListeners()
diff --git a/javax/swing/plaf/basic/BasicTextUI.java b/javax/swing/plaf/basic/BasicTextUI.java
index 5febe141d..f201984db 100644
--- a/javax/swing/plaf/basic/BasicTextUI.java
+++ b/javax/swing/plaf/basic/BasicTextUI.java
@@ -83,7 +83,6 @@ import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;
import javax.swing.text.Keymap;
import javax.swing.text.Position;
-import javax.swing.text.Utilities;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
@@ -242,6 +241,12 @@ public abstract class BasicTextUI extends TextUI
return Integer.MAX_VALUE;
}
+ public void setSize(float w, float h)
+ {
+ if (view != null)
+ view.setSize(w, h);
+ }
+
/**
* Paints the view. This is delegated to the real root view.
*
@@ -861,6 +866,7 @@ public abstract class BasicTextUI extends TextUI
protected void uninstallListeners()
{
textComponent.removeFocusListener(focuslistener);
+ textComponent.getDocument().removeDocumentListener(documentHandler);
}
/**
@@ -892,14 +898,19 @@ public abstract class BasicTextUI extends TextUI
*/
public Dimension getPreferredSize(JComponent c)
{
- View v = getRootView(textComponent);
-
- float w = v.getPreferredSpan(View.X_AXIS);
- float h = v.getPreferredSpan(View.Y_AXIS);
-
+ Dimension d = c.getSize();
Insets i = c.getInsets();
- return new Dimension((int) w + i.left + i.right,
+ if (d.width > (i.left + i.right) && d.height > (i.top + i.bottom))
+ {
+ rootView.setSize(d.width - i.left - i.right,
+ d.height - i.top - i.bottom);
+ }
+ float w = rootView.getPreferredSpan(View.X_AXIS);
+ float h = rootView.getPreferredSpan(View.Y_AXIS);
+
+ Dimension size = new Dimension((int) w + i.left + i.right,
(int) h + i.top + i.bottom);
+ return size;
}
/**
@@ -1042,7 +1053,7 @@ public abstract class BasicTextUI extends TextUI
*/
public void damageRange(JTextComponent t, int p0, int p1)
{
- damageRange(t, p0, p1, null, null);
+ damageRange(t, p0, p1, Position.Bias.Forward, Position.Bias.Backward);
}
/**
@@ -1062,106 +1073,36 @@ public abstract class BasicTextUI extends TextUI
public void damageRange(JTextComponent t, int p0, int p1,
Position.Bias firstBias, Position.Bias secondBias)
{
- // Do nothing if the component cannot be properly displayed.
- if (t.getWidth() == 0 || t.getHeight() == 0)
- return;
-
- try
+ Rectangle alloc = getVisibleEditorRect();
+ if (alloc != null)
{
- // Limit p0 and p1 to sane values to prevent unfriendly
- // BadLocationExceptions. This makes it possible for the highlighter
- // to send us illegal values which can happen when a large number
- // of selected characters are removed (eg. by pressing delete
- // or backspace).
- // The reference implementation does not throw an exception, too.
- p0 = Math.min(p0, t.getDocument().getLength());
- p1 = Math.min(p1, t.getDocument().getLength());
-
- Rectangle l1 = modelToView(t, p0, firstBias);
- Rectangle l2 = modelToView(t, p1, secondBias);
- if (l1 == null || l2 == null)
+ Document doc = t.getDocument();
+
+ // Acquire lock here to avoid structural changes in between.
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).readLock();
+ try
{
- // Unable to determine the start or end of the selection.
- t.repaint();
+ rootView.setSize(alloc.width, alloc.height);
+ Shape damage = rootView.modelToView(p0, firstBias, p1, secondBias,
+ alloc);
+ Rectangle r = damage instanceof Rectangle ? (Rectangle) damage
+ : damage.getBounds();
+ textComponent.repaint(r.x, r.y, r.width, r.height);
}
- else if (l1.y == l2.y)
+ catch (BadLocationException ex)
{
- SwingUtilities.computeUnion(l2.x, l2.y, l2.width, l2.height, l1);
- t.repaint(l1);
+ // Lets ignore this as it causes no serious problems.
+ // For debugging, comment this out.
+ // ex.printStackTrace();
}
- else
+ finally
{
- // The two rectangles lie on different lines and we need a
- // different algorithm to calculate the damaged area:
- // 1. The line of p0 is damaged from the position of p0
- // to the right border.
- // 2. All lines between the ones where p0 and p1 lie on
- // are completely damaged. Use the allocation area to find
- // out the bounds.
- // 3. The final line is damaged from the left bound to the
- // position of p1.
- Insets insets = t.getInsets();
-
- // Damage first line until the end.
- l1.width = insets.right + t.getWidth() - l1.x;
- t.repaint(l1);
-
- // Note: Utilities.getPositionBelow() may return the offset
- // that was put in. In that case there is no next line and
- // we should stop searching for one.
-
- int posBelow = Utilities.getPositionBelow(t, p0, l1.x);
- int p1RowStart = Utilities.getRowStart(t, p1);
-
- if (posBelow != -1
- && posBelow != p0
- && Utilities.getRowStart(t, posBelow) != p1RowStart)
- {
- // Take the rectangle of the offset we just found and grow it
- // to the maximum width. Retain y because this is our start
- // height.
- Rectangle grow = modelToView(t, posBelow);
- grow.x = insets.left;
- grow.width = t.getWidth() + insets.right;
-
- // Find further lines which have to be damaged completely.
- int nextPosBelow = posBelow;
- while (nextPosBelow != -1
- && posBelow != nextPosBelow
- && Utilities.getRowStart(t, nextPosBelow) != p1RowStart)
- {
- posBelow = nextPosBelow;
- nextPosBelow = Utilities.getPositionBelow(t, posBelow,
- l1.x);
-
- if (posBelow == nextPosBelow)
- break;
- }
- // Now posBelow is an offset on the last line which has to be
- // damaged completely. (newPosBelow is on the same line as p1)
-
- // Retrieve the rectangle of posBelow and use its y and height
- // value to calculate the final height of the multiple line
- // spanning rectangle.
- Rectangle end = modelToView(t, posBelow);
- grow.height = end.y + end.height - grow.y;
-
- // Mark that area as damage.
- t.repaint(grow);
- }
-
- // Damage last line from its beginning to the position of p1.
- l2.width += l2.x;
- l2.x = insets.left;
- t.repaint(l2);
+ // Release lock.
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).readUnlock();
}
}
- catch (BadLocationException ex)
- {
- AssertionError err = new AssertionError("Unexpected bad location");
- err.initCause(ex);
- throw err;
- }
}
/**
@@ -1258,10 +1199,29 @@ public abstract class BasicTextUI extends TextUI
public Rectangle modelToView(JTextComponent t, int pos, Position.Bias bias)
throws BadLocationException
{
- Rectangle r = getVisibleEditorRect();
-
- return (r != null) ? rootView.modelToView(pos, r, bias).getBounds()
- : null;
+ // We need to read-lock here because we depend on the document
+ // structure not beeing changed in between.
+ Document doc = textComponent.getDocument();
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).readLock();
+ Rectangle rect = null;
+ try
+ {
+ Rectangle r = getVisibleEditorRect();
+ if (r != null)
+ {
+ rootView.setSize(r.width, r.height);
+ Shape s = rootView.modelToView(pos, r, bias);
+ if (s != null)
+ rect = s.getBounds();
+ }
+ }
+ finally
+ {
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).readUnlock();
+ }
+ return rect;
}
/**
@@ -1276,7 +1236,7 @@ public abstract class BasicTextUI extends TextUI
*/
public int viewToModel(JTextComponent t, Point pt)
{
- return viewToModel(t, pt, null);
+ return viewToModel(t, pt, new Position.Bias[1]);
}
/**
diff --git a/javax/swing/plaf/basic/BasicToolBarUI.java b/javax/swing/plaf/basic/BasicToolBarUI.java
index a4ed0c87d..1c36b408d 100644
--- a/javax/swing/plaf/basic/BasicToolBarUI.java
+++ b/javax/swing/plaf/basic/BasicToolBarUI.java
@@ -38,8 +38,6 @@ exception statement from your version. */
package javax.swing.plaf.basic;
-import gnu.classpath.NotImplementedException;
-
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
@@ -50,6 +48,7 @@ import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
+import java.awt.event.ActionEvent;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.FocusEvent;
@@ -62,7 +61,11 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Hashtable;
+import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
+import javax.swing.Action;
+import javax.swing.ActionMap;
+import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
@@ -77,6 +80,7 @@ import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.event.MouseInputListener;
+import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.ToolBarUI;
import javax.swing.plaf.UIResource;
@@ -87,6 +91,35 @@ import javax.swing.plaf.basic.BasicBorders.ButtonBorder;
*/
public class BasicToolBarUI extends ToolBarUI implements SwingConstants
{
+
+ /**
+ * Implements the keyboard actions for JToolBar.
+ */
+ static class ToolBarAction
+ extends AbstractAction
+ {
+ /**
+ * Performs the action.
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ Object cmd = getValue("__command__");
+ JToolBar toolBar = (JToolBar) event.getSource();
+ BasicToolBarUI ui = (BasicToolBarUI) toolBar.getUI();
+
+ if (cmd.equals("navigateRight"))
+ ui.navigateFocusedComp(EAST);
+ else if (cmd.equals("navigateLeft"))
+ ui.navigateFocusedComp(WEST);
+ else if (cmd.equals("navigateUp"))
+ ui.navigateFocusedComp(NORTH);
+ else if (cmd.equals("navigateDown"))
+ ui.navigateFocusedComp(SOUTH);
+ else
+ assert false : "Shouldn't reach here";
+ }
+ }
+
/** Static owner of all DragWindows.
* This is package-private to avoid an accessor method. */
static JFrame owner = new JFrame();
@@ -619,9 +652,46 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants
* by the look and feel.
*/
protected void installKeyboardActions()
- throws NotImplementedException
{
- // FIXME: implement.
+ // Install the input map.
+ InputMap inputMap =
+ (InputMap) SharedUIDefaults.get("ToolBar.ancestorInputMap");
+ SwingUtilities.replaceUIInputMap(toolBar,
+ JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
+ inputMap);
+
+ // FIXME: The JDK uses a LazyActionMap for parentActionMap
+ SwingUtilities.replaceUIActionMap(toolBar, getActionMap());
+ }
+
+ /**
+ * Fetches the action map from the UI defaults, or create a new one
+ * if the action map hasn't been initialized.
+ *
+ * @return the action map
+ */
+ private ActionMap getActionMap()
+ {
+ ActionMap am = (ActionMap) UIManager.get("ToolBar.actionMap");
+ if (am == null)
+ {
+ am = createDefaultActions();
+ UIManager.getLookAndFeelDefaults().put("ToolBar.actionMap", am);
+ }
+ return am;
+ }
+
+ private ActionMap createDefaultActions()
+ {
+ ActionMapUIResource am = new ActionMapUIResource();
+ Action action = new ToolBarAction();
+
+ am.put("navigateLeft", action);
+ am.put("navigateRight", action);
+ am.put("navigateUp", action);
+ am.put("navigateDown", action);
+
+ return am;
}
/**
@@ -643,7 +713,12 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants
floatFrame.addWindowListener(windowListener);
toolBarFocusListener = createToolBarFocusListener();
- toolBar.addFocusListener(toolBarFocusListener);
+ if (toolBarFocusListener != null)
+ {
+ int count = toolBar.getComponentCount();
+ for (int i = 0; i < count; i++)
+ toolBar.getComponent(i).addFocusListener(toolBarFocusListener);
+ }
}
/**
@@ -758,9 +833,55 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants
* @param direction The direction to give focus to.
*/
protected void navigateFocusedComp(int direction)
- throws NotImplementedException
{
- // FIXME: Implement.
+ int count = toolBar.getComponentCount();
+ switch (direction)
+ {
+ case EAST:
+ case SOUTH:
+ if (focusedCompIndex >= 0 && focusedCompIndex < count)
+ {
+ int i = focusedCompIndex + 1;
+ boolean focusRequested = false;
+ // Find component to focus and request focus on it.
+ while (i != focusedCompIndex && ! focusRequested)
+ {
+ if (i >= count)
+ i = 0;
+ Component comp = toolBar.getComponentAtIndex(i++);
+ if (comp != null && comp.isFocusable()
+ && comp.isEnabled())
+ {
+ comp.requestFocus();
+ focusRequested = true;
+ }
+ }
+ }
+ break;
+ case WEST:
+ case NORTH:
+ if (focusedCompIndex >= 0 && focusedCompIndex < count)
+ {
+ int i = focusedCompIndex - 1;
+ boolean focusRequested = false;
+ // Find component to focus and request focus on it.
+ while (i != focusedCompIndex && ! focusRequested)
+ {
+ if (i < 0)
+ i = count - 1;
+ Component comp = toolBar.getComponentAtIndex(i--);
+ if (comp != null && comp.isFocusable()
+ && comp.isEnabled())
+ {
+ comp.requestFocus();
+ focusRequested = true;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
}
/**
@@ -925,9 +1046,10 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants
* This method uninstalls keyboard actions installed by the UI.
*/
protected void uninstallKeyboardActions()
- throws NotImplementedException
{
- // FIXME: implement.
+ SwingUtilities.replaceUIInputMap(toolBar, JComponent.
+ WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);
+ SwingUtilities.replaceUIActionMap(toolBar, null);
}
/**
@@ -935,8 +1057,13 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants
*/
protected void uninstallListeners()
{
- toolBar.removeFocusListener(toolBarFocusListener);
- toolBarFocusListener = null;
+ if (toolBarFocusListener != null)
+ {
+ int count = toolBar.getComponentCount();
+ for (int i = 0; i < count; i++)
+ toolBar.getComponent(i).removeFocusListener(toolBarFocusListener);
+ toolBarFocusListener = null;
+ }
floatFrame.removeWindowListener(windowListener);
windowListener = null;
@@ -1294,6 +1421,10 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants
cachedBounds = toolBar.getPreferredSize();
cachedOrientation = toolBar.getOrientation();
+
+ Component c = e.getChild();
+ if (toolBarFocusListener != null)
+ c.addFocusListener(toolBarFocusListener);
}
/**
@@ -1307,6 +1438,10 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants
setBorderToNormal(e.getChild());
cachedBounds = toolBar.getPreferredSize();
cachedOrientation = toolBar.getOrientation();
+
+ Component c = e.getChild();
+ if (toolBarFocusListener != null)
+ c.removeFocusListener(toolBarFocusListener);
}
}
@@ -1334,29 +1469,32 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants
/**
* Creates a new ToolBarFocusListener object.
*/
- protected ToolBarFocusListener() throws NotImplementedException
+ protected ToolBarFocusListener()
{
- // FIXME: implement.
+ // Nothing to do here.
}
/**
- * DOCUMENT ME!
+ * Receives notification when the toolbar or one of it's component
+ * receives the keyboard input focus.
*
- * @param e DOCUMENT ME!
+ * @param e the focus event
*/
- public void focusGained(FocusEvent e) throws NotImplementedException
+ public void focusGained(FocusEvent e)
{
- // FIXME: implement.
+ Component c = e.getComponent();
+ focusedCompIndex = toolBar.getComponentIndex(c);
}
/**
- * DOCUMENT ME!
+ * Receives notification when the toolbar or one of it's component
+ * looses the keyboard input focus.
*
- * @param e DOCUMENT ME!
+ * @param e the focus event
*/
- public void focusLost(FocusEvent e) throws NotImplementedException
+ public void focusLost(FocusEvent e)
{
- // FIXME: implement.
+ // Do nothing here.
}
}
diff --git a/javax/swing/plaf/basic/BasicToolTipUI.java b/javax/swing/plaf/basic/BasicToolTipUI.java
index 5cec2e333..94e7bc322 100644
--- a/javax/swing/plaf/basic/BasicToolTipUI.java
+++ b/javax/swing/plaf/basic/BasicToolTipUI.java
@@ -40,19 +40,20 @@ package javax.swing.plaf.basic;
import java.awt.Color;
import java.awt.Dimension;
+import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
-import java.awt.Toolkit;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.JToolTip;
import javax.swing.LookAndFeel;
-import javax.swing.SwingConstants;
-import javax.swing.SwingUtilities;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.ToolTipUI;
+import javax.swing.text.View;
/**
* This is the Basic Look and Feel UI class for JToolTip.
@@ -60,6 +61,28 @@ import javax.swing.plaf.ToolTipUI;
public class BasicToolTipUI extends ToolTipUI
{
+ /**
+ * Receives notification when a property of the JToolTip changes.
+ * This updates the HTML renderer if appropriate.
+ */
+ private class PropertyChangeHandler
+ implements PropertyChangeListener
+ {
+
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ String prop = e.getPropertyName();
+ if (prop.equals("tiptext") || prop.equals("font")
+ || prop.equals("foreground"))
+ {
+ JToolTip tip = (JToolTip) e.getSource();
+ String text = tip.getTipText();
+ BasicHTML.updateRenderer(tip, text);
+ }
+ }
+
+ }
+
/** The shared instance of BasicToolTipUI used for all ToolTips. */
private static BasicToolTipUI shared;
@@ -67,6 +90,11 @@ public class BasicToolTipUI extends ToolTipUI
private String text;
/**
+ * Handles property changes.
+ */
+ private PropertyChangeListener propertyChangeHandler;
+
+ /**
* Creates a new BasicToolTipUI object.
*/
public BasicToolTipUI()
@@ -98,7 +126,12 @@ public class BasicToolTipUI extends ToolTipUI
*/
public Dimension getMaximumSize(JComponent c)
{
- return getPreferredSize(c);
+ Dimension d = getPreferredSize(c);
+ View view = (View) c.getClientProperty(BasicHTML.propertyKey);
+ if (view != null)
+ d.width += view.getMaximumSpan(View.X_AXIS)
+ - view.getPreferredSpan(View.X_AXIS);
+ return d;
}
/**
@@ -110,7 +143,12 @@ public class BasicToolTipUI extends ToolTipUI
*/
public Dimension getMinimumSize(JComponent c)
{
- return getPreferredSize(c);
+ Dimension d = getPreferredSize(c);
+ View view = (View) c.getClientProperty(BasicHTML.propertyKey);
+ if (view != null)
+ d.width -= view.getPreferredSpan(View.X_AXIS)
+ - view.getMinimumSpan(View.X_AXIS);
+ return d;
}
/**
@@ -123,22 +161,25 @@ public class BasicToolTipUI extends ToolTipUI
public Dimension getPreferredSize(JComponent c)
{
JToolTip tip = (JToolTip) c;
- FontMetrics fm;
- Toolkit g = tip.getToolkit();
- text = tip.getTipText();
-
- Rectangle vr = new Rectangle();
- Rectangle ir = new Rectangle();
- Rectangle tr = new Rectangle();
- Insets insets = tip.getInsets();
- fm = g.getFontMetrics(tip.getFont());
- SwingUtilities.layoutCompoundLabel(tip, fm, text, null,
- SwingConstants.CENTER,
- SwingConstants.CENTER,
- SwingConstants.CENTER,
- SwingConstants.CENTER, vr, ir, tr, 0);
- return new Dimension(insets.left + tr.width + insets.right,
- insets.top + tr.height + insets.bottom);
+ String str = tip.getTipText();
+ FontMetrics fm = c.getFontMetrics(c.getFont());
+ Insets i = c.getInsets();
+ Dimension d = new Dimension(i.left + i.right, i.top + i.bottom);
+ if (str != null && ! str.equals(""))
+ {
+ View view = (View) c.getClientProperty(BasicHTML.propertyKey);
+ if (view != null)
+ {
+ d.width += (int) view.getPreferredSpan(View.X_AXIS);
+ d.height += (int) view.getPreferredSpan(View.Y_AXIS);
+ }
+ else
+ {
+ d.width += fm.stringWidth(str) + 6;
+ d.height += fm.getHeight();
+ }
+ }
+ return d;
}
/**
@@ -160,7 +201,8 @@ public class BasicToolTipUI extends ToolTipUI
*/
protected void installListeners(JComponent c)
{
- // TODO: Implement this properly.
+ propertyChangeHandler = new PropertyChangeHandler();
+ c.addPropertyChangeListener(propertyChangeHandler);
}
/**
@@ -172,6 +214,7 @@ public class BasicToolTipUI extends ToolTipUI
{
c.setOpaque(true);
installDefaults(c);
+ BasicHTML.updateRenderer(c, ((JToolTip) c).getTipText());
installListeners(c);
}
@@ -186,26 +229,25 @@ public class BasicToolTipUI extends ToolTipUI
JToolTip tip = (JToolTip) c;
String text = tip.getTipText();
- Toolkit t = tip.getToolkit();
- if (text == null)
- return;
-
- Rectangle vr = new Rectangle();
- vr = SwingUtilities.calculateInnerArea(tip, vr);
- Rectangle ir = new Rectangle();
- Rectangle tr = new Rectangle();
- FontMetrics fm = t.getFontMetrics(tip.getFont());
+ Font font = c.getFont();
+ FontMetrics fm = c.getFontMetrics(font);
int ascent = fm.getAscent();
- SwingUtilities.layoutCompoundLabel(tip, fm, text, null,
- SwingConstants.CENTER,
- SwingConstants.CENTER,
- SwingConstants.CENTER,
- SwingConstants.CENTER, vr, ir, tr, 0);
+ Insets i = c.getInsets();
+ Dimension size = c.getSize();
+ Rectangle paintR = new Rectangle(i.left, i.top,
+ size.width - i.left - i.right,
+ size.height - i.top - i.bottom);
Color saved = g.getColor();
+ Font oldFont = g.getFont();
g.setColor(Color.BLACK);
- g.drawString(text, vr.x, vr.y + ascent);
+ View view = (View) c.getClientProperty(BasicHTML.propertyKey);
+ if (view != null)
+ view.paint(g, paintR);
+ else
+ g.drawString(text, paintR.x + 3, paintR.y + ascent);
+ g.setFont(oldFont);
g.setColor(saved);
}
@@ -229,7 +271,11 @@ public class BasicToolTipUI extends ToolTipUI
*/
protected void uninstallListeners(JComponent c)
{
- // TODO: Implement this properly.
+ if (propertyChangeHandler != null)
+ {
+ c.removePropertyChangeListener(propertyChangeHandler);
+ propertyChangeHandler = null;
+ }
}
/**
@@ -240,6 +286,7 @@ public class BasicToolTipUI extends ToolTipUI
public void uninstallUI(JComponent c)
{
uninstallDefaults(c);
+ BasicHTML.updateRenderer(c, "");
uninstallListeners(c);
}
}
diff --git a/javax/swing/plaf/basic/BasicTreeUI.java b/javax/swing/plaf/basic/BasicTreeUI.java
index 0ca30b7ad..9a193986a 100644
--- a/javax/swing/plaf/basic/BasicTreeUI.java
+++ b/javax/swing/plaf/basic/BasicTreeUI.java
@@ -238,9 +238,6 @@ public class BasicTreeUI
/** Set to true if the editor has a different size than the renderer. */
protected boolean editorHasDifferentSize;
- /** The action bound to KeyStrokes. */
- TreeAction action;
-
/** Boolean to keep track of editing. */
boolean isEditing;
@@ -477,8 +474,18 @@ public class BasicTreeUI
*/
protected void setCellRenderer(TreeCellRenderer tcr)
{
- currentCellRenderer = tcr;
+ // Finish editing before changing the renderer.
+ completeEditing();
+
+ // The renderer is set in updateRenderer.
updateRenderer();
+
+ // Refresh the layout if necessary.
+ if (treeState != null)
+ {
+ treeState.invalidateSizes();
+ updateSize();
+ }
}
/**
@@ -1071,7 +1078,6 @@ public class BasicTreeUI
*/
protected void uninstallKeyboardActions()
{
- action = null;
tree.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).setParent(
null);
tree.getActionMap().setParent(null);
@@ -1172,10 +1178,26 @@ public class BasicTreeUI
protected void updateRenderer()
{
if (tree != null)
- currentCellRenderer = tree.getCellRenderer();
-
- if (currentCellRenderer == null)
- currentCellRenderer = createDefaultCellRenderer();
+ {
+ TreeCellRenderer rend = tree.getCellRenderer();
+ if (rend != null)
+ {
+ createdRenderer = false;
+ currentCellRenderer = rend;
+ if (createdCellEditor)
+ tree.setCellEditor(null);
+ }
+ else
+ {
+ tree.setCellRenderer(createDefaultCellRenderer());
+ createdRenderer = true;
+ }
+ }
+ else
+ {
+ currentCellRenderer = null;
+ createdRenderer = false;
+ }
updateCellEditor();
}
@@ -1272,8 +1294,6 @@ public class BasicTreeUI
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
ancestorInputMap);
- action = new TreeAction();
-
SwingUtilities.replaceUIActionMap(tree, getActionMap());
}
@@ -1303,9 +1323,6 @@ public class BasicTreeUI
ActionMapUIResource am = new ActionMapUIResource();
Action action;
- action = new TreeAction();
- am.put(action.getValue(Action.NAME), action);
-
// TreeHomeAction.
action = new TreeHomeAction(-1, "selectFirst");
am.put(action.getValue(Action.NAME), action);
@@ -2034,94 +2051,6 @@ public class BasicTreeUI
}
/**
- * This class implements the actions that we want to happen when specific keys
- * are pressed for the JTree. The actionPerformed method is called when a key
- * that has been registered for the JTree is received.
- */
- class TreeAction
- extends AbstractAction
- {
-
- /**
- * What to do when this action is called.
- *
- * @param e the ActionEvent that caused this action.
- */
- public void actionPerformed(ActionEvent e)
- {
- String command = e.getActionCommand();
- TreePath lead = tree.getLeadSelectionPath();
-
- if (command.equals("selectPreviousChangeLead")
- || command.equals("selectPreviousExtendSelection")
- || command.equals("selectPrevious") || command.equals("selectNext")
- || command.equals("selectNextExtendSelection")
- || command.equals("selectNextChangeLead"))
- (new TreeIncrementAction(0, "")).actionPerformed(e);
- else if (command.equals("selectParent") || command.equals("selectChild"))
- (new TreeTraverseAction(0, "")).actionPerformed(e);
- else if (command.equals("selectAll"))
- {
- TreePath[] paths = new TreePath[treeState.getRowCount()];
- for (int i = 0; i < paths.length; i++)
- paths[i] = treeState.getPathForRow(i);
- tree.addSelectionPaths(paths);
- }
- else if (command.equals("startEditing"))
- tree.startEditingAtPath(lead);
- else if (command.equals("toggle"))
- {
- if (tree.isEditing())
- tree.stopEditing();
- else
- {
- Object last = lead.getLastPathComponent();
- TreePath path = new TreePath(getPathToRoot(last, 0));
- if (! treeModel.isLeaf(last))
- toggleExpandState(path);
- }
- }
- else if (command.equals("clearSelection"))
- tree.clearSelection();
-
- if (tree.isEditing() && ! command.equals("startEditing"))
- tree.stopEditing();
-
- tree.scrollPathToVisible(tree.getLeadSelectionPath());
- }
- }
-
- /**
- * This class is used to mimic the behaviour of the JDK when registering
- * keyboard actions. It is the same as the private class used in JComponent
- * for the same reason. This class receives an action event and dispatches it
- * to the true receiver after altering the actionCommand property of the
- * event.
- */
- private static class ActionListenerProxy
- extends AbstractAction
- {
- ActionListener target;
-
- String bindingCommandName;
-
- public ActionListenerProxy(ActionListener li, String cmd)
- {
- target = li;
- bindingCommandName = cmd;
- }
-
- public void actionPerformed(ActionEvent e)
- {
- ActionEvent derivedEvent = new ActionEvent(e.getSource(), e.getID(),
- bindingCommandName,
- e.getModifiers());
-
- target.actionPerformed(derivedEvent);
- }
- }
-
- /**
* Updates the preferred size when scrolling, if necessary.
*/
public class ComponentHandler
@@ -2503,6 +2432,9 @@ public class BasicTreeUI
}
}
}
+
+ // We need to request the focus.
+ tree.requestFocusInWindow();
}
/**
diff --git a/javax/swing/plaf/metal/MetalBorders.java b/javax/swing/plaf/metal/MetalBorders.java
index 7c41180ae..d4e3a8497 100644
--- a/javax/swing/plaf/metal/MetalBorders.java
+++ b/javax/swing/plaf/metal/MetalBorders.java
@@ -926,15 +926,11 @@ public class MetalBorders
/** The border insets. */
protected static Insets borderInsets = new Insets(1, 0, 1, 0);
- // TODO: find where this color really comes from
- private static Color borderColor = new Color(153, 153, 153);
-
/**
* Creates a new border instance.
*/
public MenuBarBorder()
{
- // Nothing to do here.
}
/**
@@ -951,7 +947,17 @@ public class MetalBorders
public void paintBorder(Component c, Graphics g, int x, int y, int w,
int h)
{
- g.setColor(borderColor);
+ // Although it is not correct to decide on the static property
+ // currentTheme which color to use the RI does it like that.
+ // The trouble is that by simply changing the current theme to
+ // e.g. DefaultMetalLookAndFeel this method will use another color
+ // although a change in painting behavior should be expected only
+ // after setting a new look and feel and updating all components.
+ if(MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme)
+ g.setColor(UIManager.getColor("MenuBar.borderColor"));
+ else
+ g.setColor(MetalLookAndFeel.getControlShadow());
+
g.drawLine(x, y + h - 1, x + w, y + h - 1);
}
diff --git a/javax/swing/plaf/metal/MetalComboBoxButton.java b/javax/swing/plaf/metal/MetalComboBoxButton.java
index 6a528de2b..265ea7ef6 100644
--- a/javax/swing/plaf/metal/MetalComboBoxButton.java
+++ b/javax/swing/plaf/metal/MetalComboBoxButton.java
@@ -259,7 +259,9 @@ public class MetalComboBoxButton
Component comp = renderer.getListCellRendererComponent(listBox,
comboBox.getSelectedItem(), -1, false, false);
comp.setFont(rendererPane.getFont());
- if (model.isArmed() && model.isPressed())
+
+ if ((model.isArmed() && model.isPressed())
+ || (comboBox.isFocusOwner() && !comboBox.isPopupVisible()))
{
if (isOpaque())
{
diff --git a/javax/swing/plaf/metal/MetalFileChooserUI.java b/javax/swing/plaf/metal/MetalFileChooserUI.java
index 1219ad9fd..824f1d802 100644
--- a/javax/swing/plaf/metal/MetalFileChooserUI.java
+++ b/javax/swing/plaf/metal/MetalFileChooserUI.java
@@ -42,6 +42,7 @@ import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
+import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.LayoutManager;
@@ -303,8 +304,9 @@ public class MetalFileChooserUI
if (file == null)
setFileName(null);
- else
- setFileName(file.getName());
+ else if (file.isFile() || filechooser.getFileSelectionMode()
+ != JFileChooser.FILES_ONLY)
+ setFileName(file.getName());
int index = -1;
index = getModel().indexOf(file);
if (index >= 0)
@@ -567,10 +569,17 @@ public class MetalFileChooserUI
extends DefaultListCellRenderer
{
/**
+ * This is the icon that is displayed in the combobox. This wraps
+ * the standard icon and adds indendation.
+ */
+ private IndentIcon indentIcon;
+
+ /**
* Creates a new renderer.
*/
public DirectoryComboBoxRenderer(JFileChooser fc)
- {
+ {
+ indentIcon = new IndentIcon();
}
/**
@@ -586,31 +595,86 @@ public class MetalFileChooserUI
* @return The list cell renderer.
*/
public Component getListCellRendererComponent(JList list, Object value,
- int index, boolean isSelected, boolean cellHasFocus)
+ int index,
+ boolean isSelected,
+ boolean cellHasFocus)
{
- FileView fileView = getFileView(getFileChooser());
+ super.getListCellRendererComponent(list, value, index, isSelected,
+ cellHasFocus);
File file = (File) value;
- setIcon(fileView.getIcon(file));
- setText(fileView.getName(file));
-
- if (isSelected)
- {
- setBackground(list.getSelectionBackground());
- setForeground(list.getSelectionForeground());
- }
- else
- {
- setBackground(list.getBackground());
- setForeground(list.getForeground());
- }
+ setText(getFileChooser().getName(file));
+
+ // Install indented icon.
+ Icon icon = getFileChooser().getIcon(file);
+ indentIcon.setIcon(icon);
+ int depth = directoryModel.getDepth(index);
+ indentIcon.setDepth(depth);
+ setIcon(indentIcon);
- setEnabled(list.isEnabled());
- setFont(list.getFont());
return this;
}
}
/**
+ * An icon that wraps another icon and adds indentation.
+ */
+ class IndentIcon
+ implements Icon
+ {
+
+ /**
+ * The indentation level.
+ */
+ private static final int INDENT = 10;
+
+ /**
+ * The wrapped icon.
+ */
+ private Icon icon;
+
+ /**
+ * The current depth.
+ */
+ private int depth;
+
+ /**
+ * Sets the icon to be wrapped.
+ *
+ * @param i the icon
+ */
+ void setIcon(Icon i)
+ {
+ icon = i;
+ }
+
+ /**
+ * Sets the indentation depth.
+ *
+ * @param d the depth to set
+ */
+ void setDepth(int d)
+ {
+ depth = d;
+ }
+
+ public int getIconHeight()
+ {
+ return icon.getIconHeight();
+ }
+
+ public int getIconWidth()
+ {
+ return icon.getIconWidth() + depth * INDENT;
+ }
+
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ icon.paintIcon(c, g, x + depth * INDENT, y);
+ }
+
+ }
+
+ /**
* A renderer for the files and directories in the file chooser.
*/
protected class FileRenderer
@@ -956,9 +1020,12 @@ public class MetalFileChooserUI
{
String text = editField.getText();
if (text != null && text != "" && !text.equals(fc.getName(editFile)))
- if (editFile.renameTo(fc.getFileSystemView().createFileObject(
- fc.getCurrentDirectory(), text)))
+ {
+ File f = fc.getFileSystemView().
+ createFileObject(fc.getCurrentDirectory(), text);
+ if ( editFile.renameTo(f) )
rescanCurrentDirectory(fc);
+ }
list.remove(editField);
}
startEditing = false;
@@ -982,17 +1049,8 @@ public class MetalFileChooserUI
*/
public void actionPerformed(ActionEvent e)
{
- if (e.getActionCommand().equals("notify-field-accept"))
+ if (editField != null)
completeEditing();
- else if (editField != null)
- {
- list.remove(editField);
- startEditing = false;
- editFile = null;
- lastSelected = null;
- editField = null;
- list.repaint();
- }
}
}
}
@@ -1101,7 +1159,7 @@ public class MetalFileChooserUI
lastSelected = selVal;
if (f.isFile())
setFileName(path.substring(path.lastIndexOf("/") + 1));
- else if (fc.getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY)
+ else if (fc.getFileSelectionMode() != JFileChooser.FILES_ONLY)
setFileName(path);
}
fileTable.repaint();
@@ -1171,16 +1229,8 @@ public class MetalFileChooserUI
*/
public void actionPerformed(ActionEvent e)
{
- if (e.getActionCommand().equals("notify-field-accept"))
+ if (editField != null)
completeEditing();
- else if (editField != null)
- {
- table.remove(editField);
- startEditing = false;
- editFile = null;
- editField = null;
- table.repaint();
- }
}
}
diff --git a/javax/swing/plaf/metal/MetalLookAndFeel.java b/javax/swing/plaf/metal/MetalLookAndFeel.java
index 9bc674db5..8a5a61107 100644
--- a/javax/swing/plaf/metal/MetalLookAndFeel.java
+++ b/javax/swing/plaf/metal/MetalLookAndFeel.java
@@ -1185,20 +1185,26 @@ public class MetalLookAndFeel extends BasicLookAndFeel
"SplitPaneDivider.draggingColor", Color.DARK_GRAY,
"TabbedPane.background", getControlShadow(),
+ "TabbedPane.contentBorderInsets", new InsetsUIResource(2, 2, 3, 3),
+ "TabbedPane.contentOpaque", Boolean.TRUE,
"TabbedPane.darkShadow", getControlDarkShadow(),
"TabbedPane.focus", getPrimaryControlDarkShadow(),
"TabbedPane.font", new FontUIResource("Dialog", Font.BOLD, 12),
"TabbedPane.foreground", getControlTextColor(),
"TabbedPane.highlight", getControlHighlight(),
"TabbedPane.light", getControl(),
- "TabbedPane.selected", getControl(),
+ "TabbedPane.selected", getControl(), // overridden in OceanTheme
"TabbedPane.selectHighlight", getControlHighlight(),
"TabbedPane.selectedTabPadInsets", new InsetsUIResource(2, 2, 2, 1),
"TabbedPane.shadow", getControlShadow(),
- "TabbedPane.tabAreaBackground", getControl(),
- "TabbedPane.tabAreaInsets", new InsetsUIResource(4, 2, 0, 6),
+ "TabbedPane.tabAreaBackground", getControl(), // overridden in OceanTheme
+ "TabbedPane.tabAreaInsets", new InsetsUIResource(4, 2, 0, 6), // dito
"TabbedPane.tabInsets", new InsetsUIResource(0, 9, 1, 9),
+ // new properties in OceanTheme:
+ // TabbedPane.contentAreaColor
+ // TabbedPane.unselectedBackground
+
"Table.background", getWindowBackground(),
"Table.focusCellBackground", getWindowBackground(),
"Table.focusCellForeground", getControlTextColor(),
diff --git a/javax/swing/plaf/metal/MetalMenuBarUI.java b/javax/swing/plaf/metal/MetalMenuBarUI.java
index ff763ea9d..40661946b 100644
--- a/javax/swing/plaf/metal/MetalMenuBarUI.java
+++ b/javax/swing/plaf/metal/MetalMenuBarUI.java
@@ -1,5 +1,5 @@
/* MetalMenuBarUI.java -- MenuBar UI for the Metal L&F
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -76,12 +76,15 @@ public class MetalMenuBarUI extends BasicMenuBarUI
*/
public void update(Graphics g, JComponent c)
{
+ int height = c.getHeight();
if (c.isOpaque()
&& UIManager.get("MenuBar.gradient") != null
- && c.getBackground() instanceof UIResource)
+ && c.getBackground() instanceof UIResource
+ && height > 2)
{
- MetalUtils.paintGradient(g, 0, 0, c.getWidth(), c.getHeight(),
+ MetalUtils.paintGradient(g, 0, 0, c.getWidth(), height - 2,
SwingConstants.VERTICAL, "MenuBar.gradient");
+
paint(g, c);
}
else
diff --git a/javax/swing/plaf/metal/MetalTabbedPaneUI.java b/javax/swing/plaf/metal/MetalTabbedPaneUI.java
index c49abe832..20135fc85 100644
--- a/javax/swing/plaf/metal/MetalTabbedPaneUI.java
+++ b/javax/swing/plaf/metal/MetalTabbedPaneUI.java
@@ -1,5 +1,5 @@
/* MetalTabbedPaneUI.java
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -170,7 +170,9 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
*/
protected LayoutManager createLayoutManager()
{
- return new TabbedPaneLayout();
+ return (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT)
+ ? new MetalTabbedPaneUI.TabbedPaneLayout()
+ : super.createLayoutManager();
}
/**
@@ -326,7 +328,6 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
int bottom = h - 1;
int right = w - 1;
-
int tabCount = tabPane.getTabCount();
int currentRun = getRunForTab(tabCount, tabIndex);
int firstIndex = tabRuns[currentRun];
@@ -396,14 +397,17 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
{
if (tabPane.getSelectedIndex() == tabIndex - 1)
{
- g.drawLine(0, 5, 0, bottom);
- g.setColor(oceanSelectedBorder);
- g.drawLine(0, 0, 0, 5);
+ g.drawLine(0, 6, 0, bottom);
+ if (tabIndex != firstIndex)
+ {
+ g.setColor(oceanSelectedBorder);
+ g.drawLine(0, 0, 0, 5);
+ }
}
else if (isSelected)
{
g.drawLine(0, 5, 0, bottom);
- if (tabIndex != 0)
+ if (tabIndex != firstIndex)
{
g.setColor(darkShadow);
g.drawLine(0, 0, 0, 5);
@@ -463,9 +467,10 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
{
Color c;
if (tabPane.getSelectedIndex() == tabIndex - 1)
- c = UIManager.getColor("TabbedPane.tabAreaBackground");
+ c = selectColor;
else
c = getUnselectedBackground(tabIndex - 1);
+ g.setColor(c);
g.fillRect(right - 5, 0, 5, 3);
g.fillRect(right - 2, 3, 2, 2);
}
@@ -522,10 +527,13 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
}
else if (isOcean && tabPane.getSelectedIndex() == tabIndex - 1)
{
- g.setColor(oceanSelectedBorder);
- g.drawLine(right, 0, right, 6);
+ if (tabIndex != firstIndex)
+ {
+ g.setColor(oceanSelectedBorder);
+ g.drawLine(right, 0, right, 6);
+ }
g.setColor(darkShadow);
- g.drawLine(right, 6, right, bottom);
+ g.drawLine(right, 7, right, bottom);
}
else if (tabIndex != firstIndex)
{
@@ -598,8 +606,10 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
if (isOcean && isSelected)
{
g.drawLine(0, 0, 0, bottom - 5);
- if ((currentRun == 0 && tabIndex != 0)
- || (currentRun > 0 && tabIndex != tabRuns[currentRun - 1]))
+
+ // Paint a connecting line to the tab below for all
+ // but the first tab in the last run.
+ if (tabIndex != tabRuns[runCount-1])
{
g.setColor(darkShadow);
g.drawLine(0, bottom - 5, 0, bottom);
@@ -688,6 +698,103 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
}
/**
+ * This method paints the focus rectangle around the selected tab.
+ *
+ * @param g The Graphics object to paint with.
+ * @param tabPlacement The JTabbedPane's tab placement.
+ * @param rects The array of rectangles keeping track of size and position.
+ * @param tabIndex The tab index.
+ * @param iconRect The icon bounds.
+ * @param textRect The text bounds.
+ * @param isSelected Whether this tab is selected.
+ */
+ protected void paintFocusIndicator(Graphics g, int tabPlacement,
+ Rectangle[] rects, int tabIndex,
+ Rectangle iconRect, Rectangle textRect,
+ boolean isSelected)
+ {
+ if (tabPane.hasFocus() && isSelected)
+ {
+ Rectangle rect = rects[tabIndex];
+
+ g.setColor(focus);
+ g.translate(rect.x, rect.y);
+
+ switch (tabPlacement)
+ {
+ case LEFT:
+ // Top line
+ g.drawLine(7, 2, rect.width-2, 2);
+
+ // Right line
+ g.drawLine(rect.width-1, 2, rect.width-1, rect.height-3);
+
+ // Bottom line
+ g.drawLine(rect.width-2, rect.height-2, 3, rect.height-2);
+
+ // Left line
+ g.drawLine(2, rect.height-3, 2, 7);
+
+ // Slant
+ g.drawLine(2, 6, 6, 2);
+ break;
+ case RIGHT:
+ // Top line
+ g.drawLine(1, 2, rect.width-8, 2);
+
+ // Slant
+ g.drawLine(rect.width-7, 2, rect.width-3, 6);
+
+ // Right line
+ g.drawLine(rect.width-3, 7, rect.width-3, rect.height-3);
+
+ // Bottom line
+ g.drawLine(rect.width-3, rect.height-2, 2, rect.height-2);
+
+ // Left line
+ g.drawLine(1, rect.height-2, 1, 2);
+ break;
+ case BOTTOM:
+ // Top line
+ g.drawLine(2, 1, rect.width-2, 1);
+
+ // Right line
+ g.drawLine(rect.width-1, 2, rect.width-1, rect.height-3);
+
+ // Bottom line
+ g.drawLine(7, rect.height-3, rect.width-2, rect.height-3);
+
+ // Slant
+ g.drawLine(6, rect.height-3, 2, rect.height-7);
+
+ // Left line
+ g.drawLine(2, rect.height-8, 2, 2);
+
+ break;
+ case TOP:
+ default:
+ // Top line
+ g.drawLine(6, 2, rect.width-2, 2);
+
+ // Right line
+ g.drawLine(rect.width-1, 2, rect.width-1, rect.height-3);
+
+ // Bottom line
+ g.drawLine(3, rect.height-3, rect.width-2, rect.height-3);
+
+ // Left line
+ g.drawLine(2, rect.height-3, 2, 7);
+
+ // Slant
+ g.drawLine(2, 6, 6, 2);
+
+ }
+
+ g.translate(-rect.x, -rect.y);
+ }
+ }
+
+ /**
* Returns <code>true</code> if the tabs in the specified run should be
* padded to make the run fill the width/height of the {@link JTabbedPane}.
*
@@ -1144,4 +1251,19 @@ public class MetalTabbedPaneUI extends BasicTabbedPaneUI
bg = unselectedBackground;
return bg;
}
+
+ protected int getTabLabelShiftX(int tabPlacement,
+ int index,
+ boolean isSelected)
+ {
+ return 0;
+ }
+
+ protected int getTabLabelShiftY(int tabPlacement,
+ int index,
+ boolean isSelected)
+ {
+ return 0;
+ }
+
}
diff --git a/javax/swing/plaf/metal/MetalToolTipUI.java b/javax/swing/plaf/metal/MetalToolTipUI.java
index d1040347f..6647cc02d 100644
--- a/javax/swing/plaf/metal/MetalToolTipUI.java
+++ b/javax/swing/plaf/metal/MetalToolTipUI.java
@@ -43,9 +43,6 @@ import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
-import java.awt.Insets;
-import java.awt.Rectangle;
-import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
@@ -54,8 +51,6 @@ import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JToolTip;
import javax.swing.KeyStroke;
-import javax.swing.SwingConstants;
-import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.plaf.ComponentUI;
@@ -192,32 +187,14 @@ public class MetalToolTipUI
*/
public Dimension getPreferredSize(JComponent c)
{
- if (isAcceleratorHidden())
- return super.getPreferredSize(c);
- else
+ Dimension d = super.getPreferredSize(c);
+ String acc = getAcceleratorString();
+ if (acc != null && ! acc.equals(""))
{
- Insets insets = c.getInsets();
- JToolTip tt = (JToolTip) c;
- String tipText = tt.getTipText();
- if (tipText != null)
- {
- FontMetrics fm = c.getFontMetrics(c.getFont());
- int prefH = fm.getHeight() + insets.top + insets.bottom;
- int prefW = fm.stringWidth(tipText) + insets.left + insets.right;
-
- // this seems to be the first opportunity we have to get the
- // accelerator string from the component (if it has one)
- acceleratorString = fetchAcceleratorString(c);
- if (acceleratorString != null)
- {
- prefW += padSpaceBetweenStrings;
- fm = c.getFontMetrics(acceleratorFont);
- prefW += fm.stringWidth(acceleratorString);
- }
- return new Dimension(prefW, prefH);
- }
- else return new Dimension(0, 0);
+ FontMetrics fm = c.getFontMetrics(c.getFont());
+ d.width += fm.stringWidth(acc);
}
+ return d;
}
/**
@@ -228,39 +205,8 @@ public class MetalToolTipUI
*/
public void paint(Graphics g, JComponent c)
{
- JToolTip tip = (JToolTip) c;
-
- String text = tip.getTipText();
- Toolkit t = tip.getToolkit();
- if (text == null)
- return;
-
- Rectangle vr = new Rectangle();
- vr = SwingUtilities.calculateInnerArea(tip, vr);
- Rectangle ir = new Rectangle();
- Rectangle tr = new Rectangle();
- FontMetrics fm = t.getFontMetrics(tip.getFont());
- int ascent = fm.getAscent();
- SwingUtilities.layoutCompoundLabel(tip, fm, text, null,
- SwingConstants.CENTER, SwingConstants.LEFT,
- SwingConstants.CENTER, SwingConstants.CENTER, vr, ir, tr, 0);
- Color saved = g.getColor();
- g.setColor(Color.BLACK);
-
- g.drawString(text, vr.x, vr.y + ascent);
-
- // paint accelerator
- if (acceleratorString != null)
- {
- g.setFont(acceleratorFont);
- g.setColor(acceleratorForeground);
- fm = t.getFontMetrics(acceleratorFont);
- int width = fm.stringWidth(acceleratorString);
- g.drawString(acceleratorString, vr.x + vr.width - width
- - padSpaceBetweenStrings / 2, vr.y + vr.height - fm.getDescent());
- }
-
- g.setColor(saved);
+ super.paint(g, c);
+ // Somehow paint accelerator. Keep care for possible HTML rendering.
}
/**
diff --git a/javax/swing/plaf/metal/MetalUtils.java b/javax/swing/plaf/metal/MetalUtils.java
index a61b8ded2..0c3a38d5c 100644
--- a/javax/swing/plaf/metal/MetalUtils.java
+++ b/javax/swing/plaf/metal/MetalUtils.java
@@ -107,7 +107,7 @@ class MetalUtils
for (int mX = x + xOff; mX < (x + w); mX += 4)
{
- g.drawLine(mX, mY, mX, mY);
+ g.fillRect(mX, mY, 1, 1);
}
// increase x offset
diff --git a/javax/swing/text/AbstractDocument.java b/javax/swing/text/AbstractDocument.java
index b936768b2..089785aa8 100644
--- a/javax/swing/text/AbstractDocument.java
+++ b/javax/swing/text/AbstractDocument.java
@@ -38,8 +38,11 @@ exception statement from your version. */
package javax.swing.text;
+import java.awt.font.TextAttribute;
import java.io.PrintStream;
import java.io.Serializable;
+import java.text.Bidi;
+import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.EventListener;
@@ -105,6 +108,21 @@ public abstract class AbstractDocument implements Document, Serializable
public static final String ElementNameAttribute = "$ename";
/**
+ * Standard name for the bidi root element.
+ */
+ private static final String BidiRootName = "bidi root";
+
+ /**
+ * Key for storing the asynchronous load priority.
+ */
+ private static final String AsyncLoadPriority = "load priority";
+
+ /**
+ * Key for storing the I18N state.
+ */
+ private static final String I18N = "i18n";
+
+ /**
* The actual content model of this <code>Document</code>.
*/
Content content;
@@ -147,14 +165,19 @@ public abstract class AbstractDocument implements Document, Serializable
/**
* A condition variable that readers and writers wait on.
*/
- Object documentCV = new Object();
+ private Object documentCV = new Object();
/** An instance of a DocumentFilter.FilterBypass which allows calling
* the insert, remove and replace method without checking for an installed
* document filter.
*/
- DocumentFilter.FilterBypass bypass;
-
+ private DocumentFilter.FilterBypass bypass;
+
+ /**
+ * The bidi root element.
+ */
+ private BidiRootElement bidiRoot;
+
/**
* Creates a new <code>AbstractDocument</code> with the specified
* {@link Content} model.
@@ -186,9 +209,25 @@ public abstract class AbstractDocument implements Document, Serializable
content = doc;
context = ctx;
+ // FIXME: Fully implement bidi.
+ bidiRoot = new BidiRootElement();
+
// FIXME: This is determined using a Mauve test. Make the document
// actually use this.
- putProperty("i18n", Boolean.FALSE);
+ putProperty(I18N, Boolean.FALSE);
+
+ // Add one child to the bidi root.
+ writeLock();
+ try
+ {
+ Element[] children = new Element[1];
+ children[0] = new BidiElement(bidiRoot, 0, 1, 0);
+ bidiRoot.replace(0, 0, children);
+ }
+ finally
+ {
+ writeUnlock();
+ }
}
/** Returns the DocumentFilter.FilterBypass instance for this
@@ -344,7 +383,11 @@ public abstract class AbstractDocument implements Document, Serializable
*/
public int getAsynchronousLoadPriority()
{
- return 0;
+ Object val = getProperty(AsyncLoadPriority);
+ int prio = -1;
+ if (val != null)
+ prio = ((Integer) val).intValue();
+ return prio;
}
/**
@@ -364,7 +407,7 @@ public abstract class AbstractDocument implements Document, Serializable
*/
public Element getBidiRootElement()
{
- return null;
+ return bidiRoot;
}
/**
@@ -417,14 +460,17 @@ public abstract class AbstractDocument implements Document, Serializable
*/
public final Position getEndPosition()
{
- // FIXME: Properly implement this by calling Content.createPosition().
- return new Position()
- {
- public int getOffset()
- {
- return getLength();
- }
- };
+ Position p;
+ try
+ {
+ p = createPosition(content.length());
+ }
+ catch (BadLocationException ex)
+ {
+ // Shouldn't really happen.
+ p = null;
+ }
+ return p;
}
/**
@@ -481,8 +527,9 @@ public abstract class AbstractDocument implements Document, Serializable
*/
public Element[] getRootElements()
{
- Element[] elements = new Element[1];
+ Element[] elements = new Element[2];
elements[0] = getDefaultRootElement();
+ elements[1] = getBidiRootElement();
return elements;
}
@@ -495,14 +542,17 @@ public abstract class AbstractDocument implements Document, Serializable
*/
public final Position getStartPosition()
{
- // FIXME: Properly implement this using Content.createPosition().
- return new Position()
- {
- public int getOffset()
- {
- return 0;
- }
- };
+ Position p;
+ try
+ {
+ p = createPosition(0);
+ }
+ catch (BadLocationException ex)
+ {
+ // Shouldn't really happen.
+ p = null;
+ }
+ return p;
}
/**
@@ -565,11 +615,19 @@ public abstract class AbstractDocument implements Document, Serializable
// Bail out if we have a bogus insertion (Behavior observed in RI).
if (text == null || text.length() == 0)
return;
-
- if (documentFilter == null)
- insertStringImpl(offset, text, attributes);
- else
- documentFilter.insertString(getBypass(), offset, text, attributes);
+
+ writeLock();
+ try
+ {
+ if (documentFilter == null)
+ insertStringImpl(offset, text, attributes);
+ else
+ documentFilter.insertString(getBypass(), offset, text, attributes);
+ }
+ finally
+ {
+ writeUnlock();
+ }
}
void insertStringImpl(int offset, String text, AttributeSet attributes)
@@ -582,23 +640,30 @@ public abstract class AbstractDocument implements Document, Serializable
new DefaultDocumentEvent(offset, text.length(),
DocumentEvent.EventType.INSERT);
- try
- {
- writeLock();
- UndoableEdit undo = content.insertString(offset, text);
- if (undo != null)
- event.addEdit(undo);
-
- insertUpdate(event, attributes);
+ UndoableEdit undo = content.insertString(offset, text);
+ if (undo != null)
+ event.addEdit(undo);
- fireInsertUpdate(event);
- if (undo != null)
- fireUndoableEditUpdate(new UndoableEditEvent(this, undo));
- }
- finally
+ // Check if we need bidi layout.
+ if (getProperty(I18N).equals(Boolean.FALSE))
{
- writeUnlock();
+ Object dir = getProperty(TextAttribute.RUN_DIRECTION);
+ if (TextAttribute.RUN_DIRECTION_RTL.equals(dir))
+ putProperty(I18N, Boolean.TRUE);
+ else
+ {
+ char[] chars = text.toCharArray();
+ if (Bidi.requiresBidi(chars, 0, chars.length))
+ putProperty(I18N, Boolean.TRUE);
+ }
}
+
+ insertUpdate(event, attributes);
+
+ fireInsertUpdate(event);
+
+ if (undo != null)
+ fireUndoableEditUpdate(new UndoableEditEvent(this, undo));
}
/**
@@ -611,7 +676,8 @@ public abstract class AbstractDocument implements Document, Serializable
*/
protected void insertUpdate(DefaultDocumentEvent chng, AttributeSet attr)
{
- // Do nothing here. Subclasses may want to override this.
+ if (Boolean.TRUE.equals(getProperty(I18N)))
+ updateBidi(chng);
}
/**
@@ -623,7 +689,8 @@ public abstract class AbstractDocument implements Document, Serializable
*/
protected void postRemoveUpdate(DefaultDocumentEvent chng)
{
- // Do nothing here. Subclasses may want to override this.
+ if (Boolean.TRUE.equals(getProperty(I18N)))
+ updateBidi(chng);
}
/**
@@ -638,7 +705,317 @@ public abstract class AbstractDocument implements Document, Serializable
if (properties == null)
properties = new Hashtable();
- properties.put(key, value);
+ if (value == null)
+ properties.remove(key);
+ else
+ properties.put(key, value);
+
+ // Update bidi structure if the RUN_DIRECTION is set.
+ if (TextAttribute.RUN_DIRECTION.equals(key))
+ {
+ if (TextAttribute.RUN_DIRECTION_RTL.equals(value)
+ && Boolean.FALSE.equals(getProperty(I18N)))
+ putProperty(I18N, Boolean.TRUE);
+
+ if (Boolean.TRUE.equals(getProperty(I18N)))
+ {
+ writeLock();
+ try
+ {
+ DefaultDocumentEvent ev =
+ new DefaultDocumentEvent(0, getLength(),
+ DocumentEvent.EventType.INSERT);
+ updateBidi(ev);
+ }
+ finally
+ {
+ writeUnlock();
+ }
+ }
+ }
+ }
+
+ /**
+ * Updates the bidi element structure.
+ *
+ * @param ev the document event for the change
+ */
+ private void updateBidi(DefaultDocumentEvent ev)
+ {
+ // Determine start and end offset of the paragraphs to be scanned.
+ int start = 0;
+ int end = 0;
+ DocumentEvent.EventType type = ev.getType();
+ if (type == DocumentEvent.EventType.INSERT
+ || type == DocumentEvent.EventType.CHANGE)
+ {
+ int offs = ev.getOffset();
+ int endOffs = offs + ev.getLength();
+ start = getParagraphElement(offs).getStartOffset();
+ end = getParagraphElement(endOffs).getEndOffset();
+ }
+ else if (type == DocumentEvent.EventType.REMOVE)
+ {
+ Element par = getParagraphElement(ev.getOffset());
+ start = par.getStartOffset();
+ end = par.getEndOffset();
+ }
+ else
+ assert false : "Unknown event type";
+
+ // Determine the bidi levels for the affected range.
+ Bidi[] bidis = getBidis(start, end);
+
+ int removeFrom = 0;
+ int removeTo = 0;
+
+ int offs = 0;
+ int lastRunStart = 0;
+ int lastRunEnd = 0;
+ int lastRunLevel = 0;
+ ArrayList newEls = new ArrayList();
+ for (int i = 0; i < bidis.length; i++)
+ {
+ Bidi bidi = bidis[i];
+ int numRuns = bidi.getRunCount();
+ for (int r = 0; r < numRuns; r++)
+ {
+ if (r == 0 && i == 0)
+ {
+ if (start > 0)
+ {
+ // Try to merge with the previous element if it has the
+ // same bidi level as the first run.
+ int prevElIndex = bidiRoot.getElementIndex(start - 1);
+ removeFrom = prevElIndex;
+ Element prevEl = bidiRoot.getElement(prevElIndex);
+ AttributeSet atts = prevEl.getAttributes();
+ int prevElLevel = StyleConstants.getBidiLevel(atts);
+ if (prevElLevel == bidi.getRunLevel(r))
+ {
+ // Merge previous element with current run.
+ lastRunStart = prevEl.getStartOffset() - start;
+ lastRunEnd = bidi.getRunLimit(r);
+ lastRunLevel = bidi.getRunLevel(r);
+ }
+ else if (prevEl.getEndOffset() > start)
+ {
+ // Split previous element and replace by 2 new elements.
+ lastRunStart = 0;
+ lastRunEnd = bidi.getRunLimit(r);
+ lastRunLevel = bidi.getRunLevel(r);
+ newEls.add(new BidiElement(bidiRoot,
+ prevEl.getStartOffset(),
+ start, prevElLevel));
+ }
+ else
+ {
+ // Simply start new run at start location.
+ lastRunStart = 0;
+ lastRunEnd = bidi.getRunLimit(r);
+ lastRunLevel = bidi.getRunLevel(r);
+ removeFrom++;
+ }
+ }
+ else
+ {
+ // Simply start new run at start location.
+ lastRunStart = 0;
+ lastRunEnd = bidi.getRunLimit(r);
+ lastRunLevel = bidi.getRunLevel(r);
+ removeFrom = 0;
+ }
+ }
+ if (i == bidis.length - 1 && r == numRuns - 1)
+ {
+ if (end <= getLength())
+ {
+ // Try to merge last element with next element.
+ int nextIndex = bidiRoot.getElementIndex(end);
+ Element nextEl = bidiRoot.getElement(nextIndex);
+ AttributeSet atts = nextEl.getAttributes();
+ int nextLevel = StyleConstants.getBidiLevel(atts);
+ int level = bidi.getRunLevel(r);
+ if (lastRunLevel == level && level == nextLevel)
+ {
+ // Merge runs together.
+ if (lastRunStart + start == nextEl.getStartOffset())
+ removeTo = nextIndex - 1;
+ else
+ {
+ newEls.add(new BidiElement(bidiRoot, start + lastRunStart,
+ nextEl.getEndOffset(), level));
+ removeTo = nextIndex;
+ }
+ }
+ else if (lastRunLevel == level)
+ {
+ // Merge current and last run.
+ int endOffs = offs + bidi.getRunLimit(r);
+ newEls.add(new BidiElement(bidiRoot, start + lastRunStart,
+ start + endOffs, level));
+ if (start + endOffs == nextEl.getStartOffset())
+ removeTo = nextIndex - 1;
+ else
+ {
+ newEls.add(new BidiElement(bidiRoot, start + endOffs,
+ nextEl.getEndOffset(),
+ nextLevel));
+ removeTo = nextIndex;
+ }
+ }
+ else if (level == nextLevel)
+ {
+ // Merge current and next run.
+ newEls.add(new BidiElement(bidiRoot, start + lastRunStart,
+ start + lastRunEnd,
+ lastRunLevel));
+ newEls.add(new BidiElement(bidiRoot, start + lastRunEnd,
+ nextEl.getEndOffset(), level));
+ removeTo = nextIndex;
+ }
+ else
+ {
+ // Split next element.
+ int endOffs = offs + bidi.getRunLimit(r);
+ newEls.add(new BidiElement(bidiRoot, start + lastRunStart,
+ start + lastRunEnd,
+ lastRunLevel));
+ newEls.add(new BidiElement(bidiRoot, start + lastRunEnd,
+ start + endOffs, level));
+ newEls.add(new BidiElement(bidiRoot, start + endOffs,
+ nextEl.getEndOffset(),
+ nextLevel));
+ removeTo = nextIndex;
+ }
+ }
+ else
+ {
+ removeTo = bidiRoot.getElementIndex(end);
+ int level = bidi.getRunLevel(r);
+ int runEnd = offs + bidi.getRunLimit(r);
+
+ if (level == lastRunLevel)
+ {
+ // Merge with previous.
+ lastRunEnd = offs + runEnd;
+ newEls.add(new BidiElement(bidiRoot,
+ start + lastRunStart,
+ start + runEnd, level));
+ }
+ else
+ {
+ // Create element for last run and current run.
+ newEls.add(new BidiElement(bidiRoot, start + lastRunStart,
+ start + lastRunEnd,
+ lastRunLevel));
+ newEls.add(new BidiElement(bidiRoot,
+ start + lastRunEnd,
+ start + runEnd,
+ level));
+ }
+ }
+ }
+ else
+ {
+ int level = bidi.getRunLevel(r);
+ int runEnd = bidi.getRunLimit(r);
+
+ if (level == lastRunLevel)
+ {
+ // Merge with previous.
+ lastRunEnd = offs + runEnd;
+ }
+ else
+ {
+ // Create element for last run and update values for
+ // current run.
+ newEls.add(new BidiElement(bidiRoot, start + lastRunStart,
+ start + lastRunEnd,
+ lastRunLevel));
+ lastRunStart = lastRunEnd;
+ lastRunEnd = offs + runEnd;
+ lastRunLevel = level;
+ }
+ }
+ }
+ offs += bidi.getLength();
+ }
+
+ // Determine the bidi elements which are to be removed.
+ int numRemoved = 0;
+ if (bidiRoot.getElementCount() > 0)
+ numRemoved = removeTo - removeFrom + 1;
+ Element[] removed = new Element[numRemoved];
+ for (int i = 0; i < numRemoved; i++)
+ removed[i] = bidiRoot.getElement(removeFrom + i);
+
+ Element[] added = new Element[newEls.size()];
+ added = (Element[]) newEls.toArray(added);
+
+ // Update the event.
+ ElementEdit edit = new ElementEdit(bidiRoot, removeFrom, removed, added);
+ ev.addEdit(edit);
+
+ // Update the structure.
+ bidiRoot.replace(removeFrom, numRemoved, added);
+ }
+
+ /**
+ * Determines the Bidi objects for the paragraphs in the specified range.
+ *
+ * @param start the start of the range
+ * @param end the end of the range
+ *
+ * @return the Bidi analysers for the paragraphs in the range
+ */
+ private Bidi[] getBidis(int start, int end)
+ {
+ // Determine the default run direction from the document property.
+ Boolean defaultDir = null;
+ Object o = getProperty(TextAttribute.RUN_DIRECTION);
+ if (o instanceof Boolean)
+ defaultDir = (Boolean) o;
+
+ // Scan paragraphs and add their level arrays to the overall levels array.
+ ArrayList bidis = new ArrayList();
+ Segment s = new Segment();
+ for (int i = start; i < end;)
+ {
+ Element par = getParagraphElement(i);
+ int pStart = par.getStartOffset();
+ int pEnd = par.getEndOffset();
+
+ // Determine the default run direction of the paragraph.
+ Boolean dir = defaultDir;
+ o = par.getAttributes().getAttribute(TextAttribute.RUN_DIRECTION);
+ if (o instanceof Boolean)
+ dir = (Boolean) o;
+
+ // Bidi over the paragraph.
+ try
+ {
+ getText(pStart, pEnd - pStart, s);
+ }
+ catch (BadLocationException ex)
+ {
+ assert false : "Must not happen";
+ }
+ int flag = Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT;
+ if (dir != null)
+ {
+ if (TextAttribute.RUN_DIRECTION_LTR.equals(dir))
+ flag = Bidi.DIRECTION_LEFT_TO_RIGHT;
+ else
+ flag = Bidi.DIRECTION_RIGHT_TO_LEFT;
+ }
+ Bidi bidi = new Bidi(s.array, s.offset, null, 0, s.count, flag);
+ bidis.add(bidi);
+ i = pEnd;
+ }
+ Bidi[] ret = new Bidi[bidis.size()];
+ ret = (Bidi[]) bidis.toArray(ret);
+ return ret;
}
/**
@@ -653,6 +1030,7 @@ public abstract class AbstractDocument implements Document, Serializable
{
while (currentWriter != null || numWritersWaiting > 0)
{
+
try
{
documentCV.wait();
@@ -743,35 +1121,36 @@ public abstract class AbstractDocument implements Document, Serializable
void removeImpl(int offset, int length) throws BadLocationException
{
- if (offset < 0 || offset > getLength())
- throw new BadLocationException("Invalid remove position", offset);
-
- if (offset + length > getLength())
- throw new BadLocationException("Invalid remove length", offset);
+ // The RI silently ignores all requests that have a negative length.
+ // Don't ask my why, but that's how it is.
+ if (length > 0)
+ {
+ if (offset < 0 || offset > getLength())
+ throw new BadLocationException("Invalid remove position", offset);
- // Prevent some unneccessary method invocation (observed in the RI).
- if (length == 0)
- return;
+ if (offset + length > getLength())
+ throw new BadLocationException("Invalid remove length", offset);
- DefaultDocumentEvent event =
- new DefaultDocumentEvent(offset, length,
- DocumentEvent.EventType.REMOVE);
+ DefaultDocumentEvent event =
+ new DefaultDocumentEvent(offset, length,
+ DocumentEvent.EventType.REMOVE);
- try
- {
- writeLock();
+ try
+ {
+ writeLock();
- // The order of the operations below is critical!
- removeUpdate(event);
- UndoableEdit temp = content.remove(offset, length);
+ // The order of the operations below is critical!
+ removeUpdate(event);
+ UndoableEdit temp = content.remove(offset, length);
- postRemoveUpdate(event);
- fireRemoveUpdate(event);
+ postRemoveUpdate(event);
+ fireRemoveUpdate(event);
+ }
+ finally
+ {
+ writeUnlock();
+ }
}
- finally
- {
- writeUnlock();
- }
}
/**
@@ -804,21 +1183,28 @@ public abstract class AbstractDocument implements Document, Serializable
if (length == 0
&& (text == null || text.length() == 0))
return;
-
- if (documentFilter == null)
+
+ writeLock();
+ try
{
- // It is important to call the methods which again do the checks
- // of the arguments and the DocumentFilter because subclasses may
- // have overridden these methods and provide crucial behavior
- // which would be skipped if we call the non-checking variants.
- // An example for this is PlainDocument where insertString can
- // provide a filtering of newlines.
- remove(offset, length);
- insertString(offset, text, attributes);
+ if (documentFilter == null)
+ {
+ // It is important to call the methods which again do the checks
+ // of the arguments and the DocumentFilter because subclasses may
+ // have overridden these methods and provide crucial behavior
+ // which would be skipped if we call the non-checking variants.
+ // An example for this is PlainDocument where insertString can
+ // provide a filtering of newlines.
+ remove(offset, length);
+ insertString(offset, text, attributes);
+ }
+ else
+ documentFilter.replace(getBypass(), offset, length, text, attributes);
+ }
+ finally
+ {
+ writeUnlock();
}
- else
- documentFilter.replace(getBypass(), offset, length, text, attributes);
-
}
void replaceImpl(int offset, int length, String text,
@@ -938,7 +1324,8 @@ public abstract class AbstractDocument implements Document, Serializable
*/
public void setAsynchronousLoadPriority(int p)
{
- // TODO: Implement this properly.
+ Integer val = p >= 0 ? new Integer(p) : null;
+ putProperty(AsyncLoadPriority, val);
}
/**
@@ -1029,6 +1416,7 @@ public abstract class AbstractDocument implements Document, Serializable
public void dump(PrintStream out)
{
((AbstractElement) getDefaultRootElement()).dump(out, 0);
+ ((AbstractElement) getBidiRootElement()).dump(out, 0);
}
/**
@@ -1245,7 +1633,7 @@ public abstract class AbstractDocument implements Document, Serializable
AttributeContext ctx = getAttributeContext();
attributes = ctx.getEmptySet();
if (s != null)
- attributes = ctx.addAttributes(attributes, s);
+ addAttributes(s);
}
/**
@@ -1557,7 +1945,7 @@ public abstract class AbstractDocument implements Document, Serializable
*/
public String getName()
{
- return (String) getAttribute(NameAttribute);
+ return (String) attributes.getAttribute(ElementNameAttribute);
}
/**
@@ -1634,6 +2022,11 @@ public abstract class AbstractDocument implements Document, Serializable
b.append('\n');
}
}
+ if (getAttributeCount() > 0)
+ {
+ for (int i = 0; i < indent; ++i)
+ b.append(' ');
+ }
b.append(">\n");
// Dump element content for leaf elements.
@@ -1695,16 +2088,9 @@ public abstract class AbstractDocument implements Document, Serializable
private int numChildren;
/**
- * The cached startOffset value. This is used in the case when a
- * BranchElement (temporarily) has no child elements.
+ * The last found index in getElementIndex(). Used for faster searching.
*/
- private int startOffset;
-
- /**
- * The cached endOffset value. This is used in the case when a
- * BranchElement (temporarily) has no child elements.
- */
- private int endOffset;
+ private int lastIndex;
/**
* Creates a new <code>BranchElement</code> with the specified
@@ -1719,8 +2105,7 @@ public abstract class AbstractDocument implements Document, Serializable
super(parent, attributes);
children = new Element[1];
numChildren = 0;
- startOffset = -1;
- endOffset = -1;
+ lastIndex = -1;
}
/**
@@ -1730,7 +2115,7 @@ public abstract class AbstractDocument implements Document, Serializable
*/
public Enumeration children()
{
- if (children.length == 0)
+ if (numChildren == 0)
return null;
Vector tmp = new Vector();
@@ -1789,35 +2174,73 @@ public abstract class AbstractDocument implements Document, Serializable
*/
public int getElementIndex(int offset)
{
- // If offset is less than the start offset of our first child,
- // return 0
- if (offset < getStartOffset())
- return 0;
+ // Implemented using an improved linear search.
+ // This makes use of the fact that searches are not random but often
+ // close to the previous search. So we try to start the binary
+ // search at the last found index.
- // XXX: There is surely a better algorithm
- // as beginning from first element each time.
- for (int index = 0; index < numChildren - 1; ++index)
+ int i0 = 0; // The lower bounds.
+ int i1 = numChildren - 1; // The upper bounds.
+ int index = -1; // The found index.
+
+ int p0 = getStartOffset();
+ int p1; // Start and end offset local variables.
+
+ if (numChildren == 0)
+ index = 0;
+ else if (offset >= getEndOffset())
+ index = numChildren - 1;
+ else
{
- Element elem = children[index];
-
- if ((elem.getStartOffset() <= offset)
- && (offset < elem.getEndOffset()))
- return index;
- // If the next element's start offset is greater than offset
- // then we have to return the closest Element, since no Elements
- // will contain the offset
- if (children[index + 1].getStartOffset() > offset)
+ // Try lastIndex.
+ if (lastIndex >= i0 && lastIndex <= i1)
{
- if ((offset - elem.getEndOffset()) > (children[index + 1].getStartOffset() - offset))
- return index + 1;
+ Element last = getElement(lastIndex);
+ p0 = last.getStartOffset();
+ p1 = last.getEndOffset();
+ if (offset >= p0 && offset < p1)
+ index = lastIndex;
else
- return index;
+ {
+ // Narrow the search bounds using the lastIndex, even
+ // if it hasn't been a hit.
+ if (offset < p0)
+ i1 = lastIndex;
+ else
+ i0 = lastIndex;
+ }
+ }
+ // The actual search.
+ int i = 0;
+ while (i0 <= i1 && index == -1)
+ {
+ i = i0 + (i1 - i0) / 2;
+ Element el = getElement(i);
+ p0 = el.getStartOffset();
+ p1 = el.getEndOffset();
+ if (offset >= p0 && offset < p1)
+ {
+ // Found it!
+ index = i;
+ }
+ else if (offset < p0)
+ i1 = i - 1;
+ else
+ i0 = i + 1;
}
- }
- // If offset is greater than the index of the last element, return
- // the index of the last element.
- return getElementCount() - 1;
+ if (index == -1)
+ {
+ // Didn't find it. Return the boundary index.
+ if (offset < p0)
+ index = i;
+ else
+ index = i + 1;
+ }
+
+ lastIndex = index;
+ }
+ return index;
}
/**
@@ -1833,15 +2256,11 @@ public abstract class AbstractDocument implements Document, Serializable
*/
public int getEndOffset()
{
- if (numChildren == 0)
- {
- if (endOffset == -1)
- throw new NullPointerException("BranchElement has no children.");
- }
- else
- endOffset = children[numChildren - 1].getEndOffset();
-
- return endOffset;
+ // This might accss one cached element or trigger an NPE for
+ // numChildren == 0. This is checked by a Mauve test.
+ Element child = numChildren > 0 ? children[numChildren - 1]
+ : children[0];
+ return child.getEndOffset();
}
/**
@@ -1867,15 +2286,13 @@ public abstract class AbstractDocument implements Document, Serializable
*/
public int getStartOffset()
{
- if (numChildren == 0)
- {
- if (startOffset == -1)
- throw new NullPointerException("BranchElement has no children.");
- }
- else
- startOffset = children[0].getStartOffset();
-
- return startOffset;
+ // Do not explicitly throw an NPE here. If the first element is null
+ // then the NPE gets thrown anyway. If it isn't, then it either
+ // holds a real value (for numChildren > 0) or a cached value
+ // (for numChildren == 0) as we don't fully remove elements in replace()
+ // when removing single elements.
+ // This is checked by a Mauve test.
+ return children[0].getStartOffset();
}
/**
@@ -1924,27 +2341,26 @@ public abstract class AbstractDocument implements Document, Serializable
*/
public void replace(int offset, int length, Element[] elements)
{
- if (numChildren + elements.length - length > children.length)
+ int delta = elements.length - length;
+ int copyFrom = offset + length; // From where to copy.
+ int copyTo = copyFrom + delta; // Where to copy to.
+ int numMove = numChildren - copyFrom; // How many elements are moved.
+ if (numChildren + delta > children.length)
{
// Gotta grow the array.
- int newSize = Math.max(2 * children.length,
- numChildren + elements.length - length);
+ int newSize = Math.max(2 * children.length, numChildren + delta);
Element[] target = new Element[newSize];
System.arraycopy(children, 0, target, 0, offset);
System.arraycopy(elements, 0, target, offset, elements.length);
- System.arraycopy(children, offset + length, target,
- offset + elements.length,
- numChildren - offset - length);
+ System.arraycopy(children, copyFrom, target, copyTo, numMove);
children = target;
}
else
{
- System.arraycopy(children, offset + length, children,
- offset + elements.length,
- numChildren - offset - length);
+ System.arraycopy(children, copyFrom, children, copyTo, numMove);
System.arraycopy(elements, 0, children, offset, elements.length);
}
- numChildren += elements.length - length;
+ numChildren += delta;
}
/**
@@ -2344,7 +2760,63 @@ public abstract class AbstractDocument implements Document, Serializable
+ getStartOffset() + "," + getEndOffset() + "\n");
}
}
-
+
+ /**
+ * The root element for bidirectional text.
+ */
+ private class BidiRootElement
+ extends BranchElement
+ {
+ /**
+ * Creates a new bidi root element.
+ */
+ BidiRootElement()
+ {
+ super(null, null);
+ }
+
+ /**
+ * Returns the name of the element.
+ *
+ * @return the name of the element
+ */
+ public String getName()
+ {
+ return BidiRootName;
+ }
+ }
+
+ /**
+ * A leaf element for the bidi structure.
+ */
+ private class BidiElement
+ extends LeafElement
+ {
+ /**
+ * Creates a new BidiElement.
+ *
+ * @param parent the parent element
+ * @param start the start offset
+ * @param end the end offset
+ * @param level the bidi level
+ */
+ BidiElement(Element parent, int start, int end, int level)
+ {
+ super(parent, new SimpleAttributeSet(), start, end);
+ addAttribute(StyleConstants.BidiLevel, new Integer(level));
+ }
+
+ /**
+ * Returns the name of the element.
+ *
+ * @return the name of the element
+ */
+ public String getName()
+ {
+ return BidiElementName;
+ }
+ }
+
/** A class whose methods delegate to the insert, remove and replace methods
* of this document which do not check for an installed DocumentFilter.
*/
diff --git a/javax/swing/text/BoxView.java b/javax/swing/text/BoxView.java
index a184a8131..7e8f19f74 100644
--- a/javax/swing/text/BoxView.java
+++ b/javax/swing/text/BoxView.java
@@ -67,6 +67,11 @@ public class BoxView
private boolean[] layoutValid = new boolean[2];
/**
+ * Indicates if the requirements for an axis are valid.
+ */
+ private boolean[] requirementsValid = new boolean[2];
+
+ /**
* The spans along the X_AXIS and Y_AXIS.
*/
private int[][] spans = new int[2][];
@@ -265,8 +270,10 @@ public class BoxView
super.replace(offset, length, views);
// Invalidate layout information.
- layoutChanged(X_AXIS);
- layoutChanged(Y_AXIS);
+ layoutValid[X_AXIS] = false;
+ requirementsValid[X_AXIS] = false;
+ layoutValid[Y_AXIS] = false;
+ requirementsValid[Y_AXIS] = false;
}
/**
@@ -278,19 +285,26 @@ public class BoxView
*/
public void paint(Graphics g, Shape a)
{
- Rectangle inside = getInsideAllocation(a);
- // TODO: Used for debugging.
- //g.drawRect(inside.x, inside.y, inside.width, inside.height);
+ Rectangle alloc;
+ if (a instanceof Rectangle)
+ alloc = (Rectangle) a;
+ else
+ alloc = a.getBounds();
+
+ int x = alloc.x + getLeftInset();
+ int y = alloc.y + getTopInset();
- Rectangle copy = new Rectangle(inside);
+ Rectangle clip = g.getClipBounds();
+ Rectangle tmp = new Rectangle();
int count = getViewCount();
for (int i = 0; i < count; ++i)
{
- copy.setBounds(inside);
- childAllocation(i, copy);
- if (!copy.isEmpty()
- && g.hitClip(copy.x, copy.y, copy.width, copy.height))
- paintChild(g, copy, i);
+ tmp.x = x + getOffset(X_AXIS, i);
+ tmp.y = y + getOffset(Y_AXIS, i);
+ tmp.width = getSpan(X_AXIS, i);
+ tmp.height = getSpan(Y_AXIS, i);
+ if (tmp.intersects(clip))
+ paintChild(g, tmp, i);
}
}
@@ -305,7 +319,13 @@ public class BoxView
public float getPreferredSpan(int axis)
{
updateRequirements(axis);
- return requirements[axis].preferred;
+ // Add margin.
+ float margin;
+ if (axis == X_AXIS)
+ margin = getLeftInset() + getRightInset();
+ else
+ margin = getTopInset() + getBottomInset();
+ return requirements[axis].preferred + margin;
}
/**
@@ -319,12 +339,14 @@ public class BoxView
*/
public float getMaximumSpan(int axis)
{
- float max;
- if (axis == myAxis)
- max = getPreferredSpan(axis);
+ updateRequirements(axis);
+ // Add margin.
+ float margin;
+ if (axis == X_AXIS)
+ margin = getLeftInset() + getRightInset();
else
- max = Integer.MAX_VALUE;
- return max;
+ margin = getTopInset() + getBottomInset();
+ return requirements[axis].maximum + margin;
}
/**
@@ -341,7 +363,13 @@ public class BoxView
public float getMinimumSpan(int axis)
{
updateRequirements(axis);
- return requirements[axis].minimum;
+ // Add margin.
+ float margin;
+ if (axis == X_AXIS)
+ margin = getLeftInset() + getRightInset();
+ else
+ margin = getTopInset() + getBottomInset();
+ return requirements[axis].minimum + margin;
}
/**
@@ -435,34 +463,29 @@ public class BoxView
protected SizeRequirements calculateMajorAxisRequirements(int axis,
SizeRequirements sr)
{
- updateChildRequirements(axis);
+ SizeRequirements res = sr;
+ if (res == null)
+ res = new SizeRequirements();
- SizeRequirements result = sr;
- if (result == null)
- result = new SizeRequirements();
+ float min = 0;
+ float pref = 0;
+ float max = 0;
- long minimum = 0;
- long preferred = 0;
- long maximum = 0;
- for (int i = 0; i < children.length; i++)
+ int n = getViewCount();
+ for (int i = 0; i < n; i++)
{
- minimum += childReqs[axis][i].minimum;
- preferred += childReqs[axis][i].preferred;
- maximum += childReqs[axis][i].maximum;
+ View child = getView(i);
+ min += child.getMinimumSpan(axis);
+ pref += child.getPreferredSpan(axis);
+ max += child.getMaximumSpan(axis);
}
- // Overflow check.
- if (minimum > Integer.MAX_VALUE)
- minimum = Integer.MAX_VALUE;
- if (preferred > Integer.MAX_VALUE)
- preferred = Integer.MAX_VALUE;
- if (maximum > Integer.MAX_VALUE)
- maximum = Integer.MAX_VALUE;
-
- result.minimum = (int) minimum;
- result.preferred = (int) preferred;
- result.maximum = (int) maximum;
- result.alignment = 0.5F;
- return result;
+
+ res.minimum = (int) min;
+ res.preferred = (int) pref;
+ res.maximum = (int) max;
+ res.alignment = 0.5F;
+
+ return res;
}
/**
@@ -480,44 +503,24 @@ public class BoxView
protected SizeRequirements calculateMinorAxisRequirements(int axis,
SizeRequirements sr)
{
- updateChildRequirements(axis);
-
SizeRequirements res = sr;
if (res == null)
res = new SizeRequirements();
- float minLeft = 0;
- float minRight = 0;
- float prefLeft = 0;
- float prefRight = 0;
- float maxLeft = 0;
- float maxRight = 0;
- for (int i = 0; i < childReqs[axis].length; i++)
+ res.minimum = 0;
+ res.preferred = 0;
+ res.maximum = 0;
+ res.alignment = 0.5F;
+ int n = getViewCount();
+ for (int i = 0; i < n; i++)
{
- float myMinLeft = childReqs[axis][i].minimum * childReqs[axis][i].alignment;
- float myMinRight = childReqs[axis][i].minimum - myMinLeft;
- minLeft = Math.max(myMinLeft, minLeft);
- minRight = Math.max(myMinRight, minRight);
- float myPrefLeft = childReqs[axis][i].preferred * childReqs[axis][i].alignment;
- float myPrefRight = childReqs[axis][i].preferred - myPrefLeft;
- prefLeft = Math.max(myPrefLeft, prefLeft);
- prefRight = Math.max(myPrefRight, prefRight);
- float myMaxLeft = childReqs[axis][i].maximum * childReqs[axis][i].alignment;
- float myMaxRight = childReqs[axis][i].maximum - myMaxLeft;
- maxLeft = Math.max(myMaxLeft, maxLeft);
- maxRight = Math.max(myMaxRight, maxRight);
+ View child = getView(i);
+ res.minimum = Math.max((int) child.getMinimumSpan(axis), res.minimum);
+ res.preferred = Math.max((int) child.getPreferredSpan(axis),
+ res.preferred);
+ res.maximum = Math.max((int) child.getMaximumSpan(axis), res.maximum);
}
- int minSize = (int) (minLeft + minRight);
- int prefSize = (int) (prefLeft + prefRight);
- int maxSize = (int) (maxLeft + maxRight);
- float align = prefLeft / (prefRight + prefLeft);
- if (Float.isNaN(align))
- align = 0;
- res.alignment = align;
- res.maximum = maxSize;
- res.preferred = prefSize;
- res.minimum = minSize;
return res;
}
@@ -565,9 +568,9 @@ public class BoxView
boolean result = false;
if (myAxis == X_AXIS)
- result = x > r.x;
+ result = x > r.x + r.width;
else
- result = y > r.y;
+ result = y > r.y + r.height;
return result;
}
@@ -620,9 +623,6 @@ public class BoxView
*/
protected void childAllocation(int index, Rectangle a)
{
- if (! isAllocationValid())
- layout(a.width, a.height);
-
a.x += offsets[X_AXIS][index];
a.y += offsets[Y_AXIS][index];
a.width = spans[X_AXIS][index];
@@ -697,15 +697,62 @@ public class BoxView
protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets,
int[] spans)
{
- updateChildRequirements(axis);
- updateRequirements(axis);
+ // Set the spans to the preferred sizes. Determine the space
+ // that we have to adjust the sizes afterwards.
+ long sumPref = 0;
+ int n = getViewCount();
+ for (int i = 0; i < n; i++)
+ {
+ View child = getView(i);
+ spans[i] = (int) child.getPreferredSpan(axis);
+ sumPref = spans[i];
+ }
- // Calculate the spans and offsets using the SizeRequirements uility
- // methods.
- SizeRequirements.calculateTiledPositions(targetSpan, requirements[axis],
- childReqs[axis],
- offsets, spans);
+ // Try to adjust the spans so that we fill the targetSpan.
+ long diff = targetSpan - sumPref;
+ float factor = 0.0F;
+ int[] diffs = null;
+ if (diff != 0)
+ {
+ long total = 0;
+ diffs = new int[n];
+ for (int i = 0; i < n; i++)
+ {
+ View child = getView(i);
+ int span;
+ if (diff < 0)
+ {
+ span = (int) child.getMinimumSpan(axis);
+ diffs[i] = spans[i] - span;
+ }
+ else
+ {
+ span = (int) child.getMaximumSpan(axis);
+ diffs[i] = span - spans[i];
+ }
+ total += span;
+ }
+ float maxAdjust = Math.abs(total - sumPref);
+ factor = diff / maxAdjust;
+ factor = Math.min(factor, 1.0F);
+ factor = Math.max(factor, -1.0F);
+ }
+
+ // Actually perform adjustments.
+ int totalOffs = 0;
+ for (int i = 0; i < n; i++)
+ {
+ offsets[i] = totalOffs;
+ if (diff != 0)
+ {
+ float adjust = factor * diffs[i];
+ spans[i] += Math.round(adjust);
+ }
+ // Avoid overflow here.
+ totalOffs = (int) Math.min((long) totalOffs + (long) spans[i],
+ Integer.MAX_VALUE);
+ }
}
/**
@@ -720,14 +767,26 @@ public class BoxView
protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets,
int[] spans)
{
- updateChildRequirements(axis);
- updateRequirements(axis);
-
- // Calculate the spans and offsets using the SizeRequirements uility
- // methods.
- SizeRequirements.calculateAlignedPositions(targetSpan, requirements[axis],
- childReqs[axis], offsets,
- spans);
+ int count = getViewCount();
+ for (int i = 0; i < count; i++)
+ {
+ View child = getView(i);
+ int max = (int) child.getMaximumSpan(axis);
+ if (max < targetSpan)
+ {
+ // Align child when it can't be made as wide as the target span.
+ float align = child.getAlignment(axis);
+ offsets[i] = (int) ((targetSpan - max) * align);
+ spans[i] = max;
+ }
+ else
+ {
+ // Expand child to target width if possible.
+ int min = (int) child.getMinimumSpan(axis);
+ offsets[i] = 0;
+ spans[i] = Math.max(min, targetSpan);
+ }
+ }
}
/**
@@ -749,7 +808,7 @@ public class BoxView
*/
public int getWidth()
{
- return span[X_AXIS];
+ return span[X_AXIS] + getLeftInset() - getRightInset();
}
/**
@@ -759,7 +818,7 @@ public class BoxView
*/
public int getHeight()
{
- return span[Y_AXIS];
+ return span[Y_AXIS] + getTopInset() - getBottomInset();
}
/**
@@ -771,7 +830,8 @@ public class BoxView
*/
public void setSize(float width, float height)
{
- layout((int) width, (int) height);
+ layout((int) (width - getLeftInset() - getRightInset()),
+ (int) (height - getTopInset() - getBottomInset()));
}
/**
@@ -822,15 +882,8 @@ public class BoxView
*/
public float getAlignment(int axis)
{
- float align;
- if (axis == myAxis)
- align = 0.5F;
- else
- {
- updateRequirements(axis);
- align = requirements[axis].alignment;
- }
- return align;
+ updateRequirements(axis);
+ return requirements[axis].alignment;
}
/**
@@ -843,9 +896,15 @@ public class BoxView
public void preferenceChanged(View child, boolean width, boolean height)
{
if (width)
- layoutValid[X_AXIS] = false;
+ {
+ layoutValid[X_AXIS] = false;
+ requirementsValid[X_AXIS] = false;
+ }
if (height)
- layoutValid[Y_AXIS] = false;
+ {
+ layoutValid[Y_AXIS] = false;
+ requirementsValid[Y_AXIS] = false;
+ }
super.preferenceChanged(child, width, height);
}
@@ -862,7 +921,7 @@ public class BoxView
if (! isAllocationValid())
{
Rectangle bounds = a.getBounds();
- layout(bounds.width, bounds.height);
+ setSize(bounds.width, bounds.height);
}
return super.modelToView(pos, a, bias);
}
@@ -963,7 +1022,9 @@ public class BoxView
*/
private void updateRequirements(int axis)
{
- if (! layoutValid[axis])
+ if (axis != Y_AXIS && axis != X_AXIS)
+ throw new IllegalArgumentException("Illegal axis: " + axis);
+ if (! requirementsValid[axis])
{
if (axis == myAxis)
requirements[axis] = calculateMajorAxisRequirements(axis,
@@ -971,6 +1032,7 @@ public class BoxView
else
requirements[axis] = calculateMinorAxisRequirements(axis,
requirements[axis]);
+ requirementsValid[axis] = true;
}
}
}
diff --git a/javax/swing/text/CompositeView.java b/javax/swing/text/CompositeView.java
index 17f13dbed..6f487b898 100644
--- a/javax/swing/text/CompositeView.java
+++ b/javax/swing/text/CompositeView.java
@@ -217,25 +217,43 @@ public abstract class CompositeView
public Shape modelToView(int pos, Shape a, Position.Bias bias)
throws BadLocationException
{
- int childIndex = getViewIndex(pos, bias);
- if (childIndex == -1)
- throw new BadLocationException("Position " + pos + " is not represented by view.", pos);
-
- Shape ret = null;
-
- View child = getView(childIndex);
- Shape childAlloc = getChildAllocation(childIndex, a);
-
- if (childAlloc == null)
- ret = createDefaultLocation(a, bias);
-
- Shape result = child.modelToView(pos, childAlloc, bias);
-
- if (result != null)
- ret = result;
- else
- ret = createDefaultLocation(a, bias);
+ boolean backward = bias == Position.Bias.Backward;
+ int testpos = backward ? Math.max(0, pos - 1) : pos;
+ Shape ret = null;
+ if (! backward || testpos >= getStartOffset())
+ {
+ int childIndex = getViewIndexAtPosition(testpos);
+ if (childIndex != -1 && childIndex < getViewCount())
+ {
+ View child = getView(childIndex);
+ if (child != null && testpos >= child.getStartOffset()
+ && testpos < child.getEndOffset())
+ {
+ Shape childAlloc = getChildAllocation(childIndex, a);
+ if (childAlloc != null)
+ {
+ ret = child.modelToView(pos, childAlloc, bias);
+ // Handle corner case.
+ if (ret == null && child.getEndOffset() == pos)
+ {
+ childIndex++;
+ if (childIndex < getViewCount())
+ {
+ child = getView(childIndex);
+ childAlloc = getChildAllocation(childIndex, a);
+ ret = child.modelToView(pos, childAlloc, bias);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ throw new BadLocationException("Position " + pos
+ + " is not represented by view.", pos);
+ }
+ }
return ret;
}
@@ -378,7 +396,10 @@ public abstract class CompositeView
{
if (b == Position.Bias.Backward && pos != 0)
pos -= 1;
- return getViewIndexAtPosition(pos);
+ int i = -1;
+ if (pos >= getStartOffset() && pos < getEndOffset())
+ i = getViewIndexAtPosition(pos);
+ return i;
}
/**
@@ -446,9 +467,13 @@ public abstract class CompositeView
*/
protected View getViewAtPosition(int pos, Rectangle a)
{
+ View view = null;
int i = getViewIndexAtPosition(pos);
- View view = children[i];
- childAllocation(i, a);
+ if (i >= 0 && i < getViewCount() && a != null)
+ {
+ view = getView(i);
+ childAllocation(i, a);
+ }
return view;
}
@@ -464,17 +489,10 @@ public abstract class CompositeView
*/
protected int getViewIndexAtPosition(int pos)
{
- int index = -1;
- for (int i = 0; i < children.length; i++)
- {
- if (children[i].getStartOffset() <= pos
- && children[i].getEndOffset() > pos)
- {
- index = i;
- break;
- }
- }
- return index;
+ // We have a 1:1 mapping of elements to views here, so we forward
+ // this to the element.
+ Element el = getElement();
+ return el.getElementIndex(pos);
}
/**
diff --git a/javax/swing/text/DefaultCaret.java b/javax/swing/text/DefaultCaret.java
index 7b4335e40..84f47f120 100644
--- a/javax/swing/text/DefaultCaret.java
+++ b/javax/swing/text/DefaultCaret.java
@@ -552,7 +552,6 @@ public class DefaultCaret extends Rectangle
*/
public void mousePressed(MouseEvent event)
{
- int button = event.getButton();
// The implementation assumes that consuming the event makes the AWT event
// mechanism forget about this event instance and not transfer focus.
@@ -565,23 +564,37 @@ public class DefaultCaret extends Rectangle
// - a middle-click positions the caret and pastes the clipboard
// contents.
// - a middle-click when shift is held down is ignored
-
- if (button == MouseEvent.BUTTON1)
- if (event.isShiftDown())
- moveCaret(event);
- else
- positionCaret(event);
- else if(button == MouseEvent.BUTTON2)
- if (event.isShiftDown())
- event.consume();
+
+ if (SwingUtilities.isLeftMouseButton(event))
+ {
+ // Handle the caret.
+ if (event.isShiftDown() && getDot() != -1)
+ {
+ moveCaret(event);
+ }
else
{
positionCaret(event);
-
+ }
+
+ // Handle the focus.
+ if (textComponent != null && textComponent.isEnabled()
+ && textComponent.isRequestFocusEnabled())
+ {
+ textComponent.requestFocus();
+ }
+
+ // TODO: Handle double click for selecting words.
+ }
+ else if(event.getButton() == MouseEvent.BUTTON2)
+ {
+ // Special handling for X11-style pasting.
+ if (! event.isShiftDown())
+ {
+ positionCaret(event);
textComponent.paste();
}
- else
- event.consume();
+ }
}
/**
@@ -898,10 +911,10 @@ public class DefaultCaret extends Rectangle
}
catch (BadLocationException e)
{
- AssertionError ae;
- ae = new AssertionError("Unexpected bad caret location: " + dot);
- ae.initCause(e);
- throw ae;
+ // Let's ignore that. This shouldn't really occur. But if it
+ // does (it seems that this happens when the model is mutating),
+ // it causes no real damage. Uncomment this for debugging.
+ // e.printStackTrace();
}
if (rect == null)
@@ -1135,10 +1148,10 @@ public class DefaultCaret extends Rectangle
}
catch (BadLocationException e)
{
- AssertionError ae;
- ae = new AssertionError("Unexpected bad caret location: " + dot);
- ae.initCause(e);
- throw ae;
+ // Let's ignore that. This shouldn't really occur. But if it
+ // does (it seems that this happens when the model is mutating),
+ // it causes no real damage. Uncomment this for debugging.
+ // e.printStackTrace();
}
if (area != null)
damage(area);
diff --git a/javax/swing/text/DefaultHighlighter.java b/javax/swing/text/DefaultHighlighter.java
index 59f77316e..69563e473 100644
--- a/javax/swing/text/DefaultHighlighter.java
+++ b/javax/swing/text/DefaultHighlighter.java
@@ -1,4 +1,4 @@
-/* DefaultHighlighter.java --
+/* DefaultHighlighter.java -- The default highlight for Swing
Copyright (C) 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,18 +38,21 @@ exception statement from your version. */
package javax.swing.text;
-import gnu.classpath.NotImplementedException;
-
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Shape;
import java.util.ArrayList;
+import java.util.Iterator;
import javax.swing.SwingUtilities;
import javax.swing.plaf.TextUI;
+/**
+ * The default highlight for Swing text components. It highlights text
+ * by filling the background with a rectangle.
+ */
public class DefaultHighlighter extends LayeredHighlighter
{
public static class DefaultHighlightPainter
@@ -68,11 +71,6 @@ public class DefaultHighlighter extends LayeredHighlighter
return color;
}
- private void paintHighlight(Graphics g, Rectangle rect)
- {
- g.fillRect(rect.x, rect.y, rect.width, rect.height);
- }
-
public void paint(Graphics g, int p0, int p1, Shape bounds,
JTextComponent t)
{
@@ -81,30 +79,31 @@ public class DefaultHighlighter extends LayeredHighlighter
Rectangle rect = bounds.getBounds();
- if (color == null)
- g.setColor(t.getSelectionColor());
- else
- g.setColor(color);
+ Color col = getColor();
+ if (col == null)
+ col = t.getSelectionColor();
+ g.setColor(col);
TextUI ui = t.getUI();
try
- {
-
- Rectangle l0 = ui.modelToView(t, p0, null);
- Rectangle l1 = ui.modelToView(t, p1, null);
-
- // Note: The computed locations may lie outside of the allocation
- // area if the text is scrolled.
+ {
+
+ Rectangle l0 = ui.modelToView(t, p0, null);
+ Rectangle l1 = ui.modelToView(t, p1, null);
- if (l0.y == l1.y)
+ // Note: The computed locations may lie outside of the allocation
+ // area if the text is scrolled.
+
+ if (l0.y == l1.y)
{
SwingUtilities.computeUnion(l0.x, l0.y, l0.width, l0.height, l1);
// Paint only inside the allocation area.
- SwingUtilities.computeIntersection(rect.x, rect.y, rect.width, rect.height, l1);
+ SwingUtilities.computeIntersection(rect.x, rect.y, rect.width,
+ rect.height, l1);
- paintHighlight(g, l1);
+ g.fillRect(l1.x, l1.y, l1.width, l1.height);
}
else
{
@@ -115,77 +114,71 @@ public class DefaultHighlighter extends LayeredHighlighter
// out the bounds.
// 3. The final line is painted from the left border to the
// position of p1.
-
- // Highlight first line until the end.
- // If rect.x is non-zero the calculation will properly adjust the
- // area to be painted.
- l0.x -= rect.x;
- l0.width = rect.width - l0.x - rect.x;
-
- paintHighlight(g, l0);
-
- int posBelow = Utilities.getPositionBelow(t, p0, l0.x);
- int p1RowStart = Utilities.getRowStart(t, p1);
- if (posBelow != -1
- && posBelow != p0
- && Utilities.getRowStart(t, posBelow)
- != p1RowStart)
- {
- Rectangle grow = ui.modelToView(t, posBelow);
- grow.x = rect.x;
- grow.width = rect.width;
-
- // Find further lines which have to be highlighted completely.
- int nextPosBelow = posBelow;
- while (nextPosBelow != -1
- && Utilities.getRowStart(t, nextPosBelow) != p1RowStart)
- {
- posBelow = nextPosBelow;
- nextPosBelow = Utilities.getPositionBelow(t, posBelow, l0.x);
-
- if (nextPosBelow == posBelow)
- break;
- }
- // Now posBelow is an offset on the last line which has to be painted
- // completely. (newPosBelow is on the same line as p1)
-
- // Retrieve the rectangle of posBelow and use its y and height
- // value to calculate the final height of the multiple line
- // spanning rectangle.
- Rectangle end = ui.modelToView(t, posBelow);
- grow.height = end.y + end.height - grow.y;
-
- paintHighlight(g, grow);
- }
-
- // Paint last line from its beginning to the position of p1.
- l1.width = l1.x + l1.width - rect.x;
- l1.x = rect.x;
- paintHighlight(g, l1);
- }
+
+ int firstLineWidth = rect.x + rect.width - l0.x;
+ g.fillRect(l0.x, l0.y, firstLineWidth, l0.height);
+ if (l0.y + l0.height != l1.y)
+ {
+ g.fillRect(rect.x, l0.y + l0.height, rect.width,
+ l1.y - l0.y - l0.height);
+ }
+ g.fillRect(rect.x, l1.y, l1.x - rect.x, l1.height);
+ }
}
catch (BadLocationException ex)
{
- AssertionError err = new AssertionError("Unexpected bad location exception");
- err.initCause(ex);
- throw err;
+ // Can't render. Comment out for debugging.
+ // ex.printStackTrace();
}
}
public Shape paintLayer(Graphics g, int p0, int p1, Shape bounds,
JTextComponent c, View view)
{
- throw new InternalError();
+ Color col = getColor();
+ if (col == null)
+ col = c.getSelectionColor();
+ g.setColor(col);
+
+ Rectangle rect = null;
+ if (p0 == view.getStartOffset() && p1 == view.getEndOffset())
+ {
+ // Paint complete bounds region.
+ rect = bounds instanceof Rectangle ? (Rectangle) bounds
+ : bounds.getBounds();
+ }
+ else
+ {
+ // Only partly inside the view.
+ try
+ {
+ Shape s = view.modelToView(p0, Position.Bias.Forward,
+ p1, Position.Bias.Backward,
+ bounds);
+ rect = s instanceof Rectangle ? (Rectangle) s : s.getBounds();
+ }
+ catch (BadLocationException ex)
+ {
+ // Can't render the highlight.
+ }
+ }
+
+ if (rect != null)
+ {
+ g.fillRect(rect.x, rect.y, rect.width, rect.height);
+ }
+ return rect;
}
}
private class HighlightEntry implements Highlighter.Highlight
{
- int p0;
- int p1;
+ Position p0;
+ Position p1;
Highlighter.HighlightPainter painter;
- public HighlightEntry(int p0, int p1, Highlighter.HighlightPainter painter)
+ public HighlightEntry(Position p0, Position p1,
+ Highlighter.HighlightPainter painter)
{
this.p0 = p0;
this.p1 = p1;
@@ -194,12 +187,12 @@ public class DefaultHighlighter extends LayeredHighlighter
public int getStartOffset()
{
- return p0;
+ return p0.getOffset();
}
public int getEndOffset()
{
- return p1;
+ return p1.getOffset();
}
public Highlighter.HighlightPainter getPainter()
@@ -209,6 +202,58 @@ public class DefaultHighlighter extends LayeredHighlighter
}
/**
+ * A HighlightEntry that is used for LayerPainter painters. In addition
+ * to the info maintained by the HighlightEntry, this class maintains
+ * a painting rectangle. This is used as repaint region when the
+ * highlight changes and the text component needs repainting.
+ */
+ private class LayerHighlightEntry
+ extends HighlightEntry
+ {
+
+ /**
+ * The paint rectangle.
+ */
+ Rectangle paintRect = new Rectangle();
+
+ LayerHighlightEntry(Position p0, Position p1,
+ Highlighter.HighlightPainter p)
+ {
+ super(p0, p1, p);
+ }
+
+ /**
+ * Paints the highlight by calling the LayerPainter. This
+ * restricts the area to be painted by startOffset and endOffset
+ * and manages the paint rectangle.
+ */
+ void paintLayeredHighlight(Graphics g, int p0, int p1, Shape bounds,
+ JTextComponent tc, View view)
+ {
+ p0 = Math.max(getStartOffset(), p0);
+ p1 = Math.min(getEndOffset(), p1);
+
+ Highlighter.HighlightPainter painter = getPainter();
+ if (painter instanceof LayerPainter)
+ {
+ LayerPainter layerPainter = (LayerPainter) painter;
+ Shape area = layerPainter.paintLayer(g, p0, p1, bounds, tc, view);
+ Rectangle rect;
+ if (area instanceof Rectangle && paintRect != null)
+ rect = (Rectangle) area;
+ else
+ rect = area.getBounds();
+
+ if (paintRect.width == 0 || paintRect.height == 0)
+ paintRect = rect.getBounds();
+ else
+ paintRect = SwingUtilities.computeUnion(rect.x, rect.y, rect.width,
+ rect.height, paintRect);
+ }
+ }
+ }
+
+ /**
* @specnote final as of 1.4
*/
public static final LayeredHighlighter.LayerPainter DefaultPainter =
@@ -254,11 +299,19 @@ public class DefaultHighlighter extends LayeredHighlighter
textComponent = null;
}
- public Object addHighlight(int p0, int p1, Highlighter.HighlightPainter painter)
+ public Object addHighlight(int p0, int p1,
+ Highlighter.HighlightPainter painter)
throws BadLocationException
{
checkPositions(p0, p1);
- HighlightEntry entry = new HighlightEntry(p0, p1, painter);
+ HighlightEntry entry;
+ Document doc = textComponent.getDocument();
+ Position pos0 = doc.createPosition(p0);
+ Position pos1 = doc.createPosition(p1);
+ if (getDrawsLayeredHighlights() && painter instanceof LayerPainter)
+ entry = new LayerHighlightEntry(pos0, pos1, painter);
+ else
+ entry = new HighlightEntry(pos0, pos1, painter);
highlights.add(entry);
textComponent.getUI().damageRange(textComponent, p0, p1);
@@ -268,16 +321,67 @@ public class DefaultHighlighter extends LayeredHighlighter
public void removeHighlight(Object tag)
{
+ HighlightEntry entry = (HighlightEntry) tag;
+ if (entry instanceof LayerHighlightEntry)
+ {
+ LayerHighlightEntry lEntry = (LayerHighlightEntry) entry;
+ Rectangle paintRect = lEntry.paintRect;
+ textComponent.repaint(paintRect.x, paintRect.y, paintRect.width,
+ paintRect.height);
+ }
+ else
+ {
+ textComponent.getUI().damageRange(textComponent,
+ entry.getStartOffset(),
+ entry.getEndOffset());
+ }
highlights.remove(tag);
- HighlightEntry entry = (HighlightEntry) tag;
- textComponent.getUI().damageRange(textComponent,
- entry.p0,
- entry.p1);
}
public void removeAllHighlights()
{
+ // Repaint damaged region.
+ int minX = 0;
+ int maxX = 0;
+ int minY = 0;
+ int maxY = 0;
+ int p0 = -1;
+ int p1 = -1;
+ for (Iterator i = highlights.iterator(); i.hasNext();)
+ {
+ HighlightEntry e = (HighlightEntry) i.next();
+ if (e instanceof LayerHighlightEntry)
+ {
+ LayerHighlightEntry le = (LayerHighlightEntry) e;
+ Rectangle r = le.paintRect;
+ minX = Math.min(r.x, minX);
+ maxX = Math.max(r.x + r.width, maxX);
+ minY = Math.min(r.y, minY);
+ maxY = Math.max(r.y + r.height, maxY);
+ }
+ else
+ {
+ if (p0 == -1 || p1 == -1)
+ {
+ p0 = e.getStartOffset();
+ p1 = e.getEndOffset();
+ }
+ else
+ {
+ p0 = Math.min(p0, e.getStartOffset());
+ p1 = Math.max(p1, e.getEndOffset());
+ }
+ }
+ if (minX != maxX && minY != maxY)
+ textComponent.repaint(minX, minY, maxX - minX, maxY - minY);
+ if (p0 != -1 && p1 != -1)
+ {
+ TextUI ui = textComponent.getUI();
+ ui.damageRange(textComponent, p0, p1);
+ }
+
+ }
highlights.clear();
}
@@ -290,94 +394,61 @@ public class DefaultHighlighter extends LayeredHighlighter
public void changeHighlight(Object tag, int n0, int n1)
throws BadLocationException
{
- int o0, o1;
-
- checkPositions(n0, n1);
- HighlightEntry entry = (HighlightEntry) tag;
- o0 = entry.p0;
- o1 = entry.p1;
-
- // Prevent useless write & repaint operations.
- if (o0 == n0 && o1 == n1)
- return;
-
- entry.p0 = n0;
- entry.p1 = n1;
-
+ Document doc = textComponent.getDocument();
TextUI ui = textComponent.getUI();
-
- // Special situation where the old area has to be cleared simply.
- if (n0 == n1)
- ui.damageRange(textComponent, o0, o1);
- // Calculates the areas where a change is really neccessary
- else if ((o1 > n0 && o1 <= n1)
- || (n1 > o0 && n1 <= o1))
+ if (tag instanceof LayerHighlightEntry)
{
- // [fds, fde) - the first damage region
- // [sds, sde] - the second damage region
- int fds, sds;
- int fde, sde;
-
- // Calculate first damaged region.
- if(o0 < n0)
- {
- // Damaged region will be cleared as
- // the old highlight region starts first.
- fds = o0;
- fde = n0;
- }
- else
- {
- // Damaged region will be painted as
- // the new highlight region starts first.
- fds = n0;
- fde = o0;
- }
-
- if (o1 < n1)
+ LayerHighlightEntry le = (LayerHighlightEntry) tag;
+ Rectangle r = le.paintRect;
+ if (r.width > 0 && r.height > 0)
+ textComponent.repaint(r.x, r.y, r.width, r.height);
+ r.width = 0;
+ r.height = 0;
+ le.p0 = doc.createPosition(n0);
+ le.p1 = doc.createPosition(n1);
+ ui.damageRange(textComponent, Math.min(n0, n1), Math.max(n0, n1));
+ }
+ else if (tag instanceof HighlightEntry)
+ {
+ HighlightEntry e = (HighlightEntry) tag;
+ int p0 = e.getStartOffset();
+ int p1 = e.getEndOffset();
+ if (p0 == n0)
{
- // Final region will be painted as the
- // old highlight region finishes first
- sds = o1;
- sde = n1;
+ ui.damageRange(textComponent, Math.min(p1, n1),
+ Math.max(p1, n1));
}
- else
+ else if (n1 == p1)
{
- // Final region will be cleared as the
- // new highlight region finishes first.
- sds = n1;
- sde = o1;
+ ui.damageRange(textComponent, Math.min(p0, n0),
+ Math.max(p0, n0));
}
-
- // If there is no undamaged region in between
- // call damageRange only once.
- if (fde == sds)
- ui.damageRange(textComponent, fds, sde);
else
{
- if (fds != fde)
- ui.damageRange(textComponent, fds, fde);
-
- if (sds != sde)
- ui.damageRange(textComponent, sds, sde);
+ ui.damageRange(textComponent, p0, p1);
+ ui.damageRange(textComponent, n0, n1);
}
+ e.p0 = doc.createPosition(n0);
+ e.p1 = doc.createPosition(n1);
}
- else
- {
- // The two regions do not overlap. So mark
- // both areas as damaged.
- ui.damageRange(textComponent, o0, o1);
- ui.damageRange(textComponent, n0, n1);
- }
-
}
public void paintLayeredHighlights(Graphics g, int p0, int p1,
Shape viewBounds, JTextComponent editor,
View view)
- throws NotImplementedException
{
- // TODO: Implement this properly.
+ for (Iterator i = highlights.iterator(); i.hasNext();)
+ {
+ Object o = i.next();
+ if (o instanceof LayerHighlightEntry)
+ {
+ LayerHighlightEntry entry = (LayerHighlightEntry) o;
+ int start = entry.getStartOffset();
+ int end = entry.getEndOffset();
+ if ((p0 < start && p1 > start) || (p0 >= start && p0 < end))
+ entry.paintLayeredHighlight(g, p0, p1, viewBounds, editor, view);
+ }
+ }
}
public void paint(Graphics g)
@@ -399,7 +470,9 @@ public class DefaultHighlighter extends LayeredHighlighter
for (int index = 0; index < size; ++index)
{
HighlightEntry entry = (HighlightEntry) highlights.get(index);
- entry.painter.paint(g, entry.p0, entry.p1, bounds, textComponent);
+ if (! (entry instanceof LayerHighlightEntry))
+ entry.painter.paint(g, entry.getStartOffset(), entry.getEndOffset(),
+ bounds, textComponent);
}
}
}
diff --git a/javax/swing/text/DefaultStyledDocument.java b/javax/swing/text/DefaultStyledDocument.java
index bd21e55c6..acc8fb6c8 100644
--- a/javax/swing/text/DefaultStyledDocument.java
+++ b/javax/swing/text/DefaultStyledDocument.java
@@ -41,7 +41,9 @@ package javax.swing.text;
import java.awt.Color;
import java.awt.Font;
import java.io.Serializable;
+import java.util.ArrayList;
import java.util.Enumeration;
+import java.util.Iterator;
import java.util.Stack;
import java.util.Vector;
@@ -424,6 +426,58 @@ public class DefaultStyledDocument extends AbstractDocument implements
*/
public class ElementBuffer implements Serializable
{
+ /**
+ * Instance of all editing information for an object in the Vector. This class
+ * is used to add information to the DocumentEvent associated with an
+ * insertion/removal/change as well as to store the changes that need to be
+ * made so they can be made all at the same (appropriate) time.
+ */
+ class Edit
+ {
+ /** The element to edit . */
+ Element e;
+
+ /** The index of the change. */
+ int index;
+
+ /** The removed elements. */
+ ArrayList removed = new ArrayList();
+
+ /** The added elements. */
+ ArrayList added = new ArrayList();
+
+ /**
+ * Indicates if this edit contains a fracture.
+ */
+ boolean isFracture;
+
+ /**
+ * Creates a new Edit for the specified element at index i.
+ *
+ * @param el the element
+ * @param i the index
+ */
+ Edit(Element el, int i)
+ {
+ this(el, i, false);
+ }
+
+ /**
+ * Creates a new Edit for the specified element at index i.
+ *
+ * @param el the element
+ * @param i the index
+ * @param frac if this is a fracture edit or not
+ */
+ Edit(Element el, int i, boolean frac)
+ {
+ e = el;
+ index = i;
+ isFracture = frac;
+ }
+
+ }
+
/** The serialization UID (compatible with JDK1.5). */
private static final long serialVersionUID = 1688745877691146623L;
@@ -442,11 +496,25 @@ public class DefaultStyledDocument extends AbstractDocument implements
/** Holds the position of the change. */
private int pos;
- /** Holds the element that was last fractured. */
- private Element lastFractured;
-
- /** True if a fracture was not created during a insertFracture call. */
- private boolean fracNotCreated;
+ /**
+ * The ElementChange that describes the latest changes.
+ */
+ private DefaultDocumentEvent documentEvent;
+
+ /**
+ * The parent of the fracture.
+ */
+ private Element fracturedParent;
+
+ /**
+ * The fractured child.
+ */
+ private Element fracturedChild;
+
+ /**
+ * Indicates if a fracture has been created.
+ */
+ private boolean createdFracture;
/**
* The current position in the element tree. This is used for bulk inserts
@@ -454,10 +522,17 @@ public class DefaultStyledDocument extends AbstractDocument implements
*/
private Stack elementStack;
+ private Edit[] insertPath;
+
+ private boolean recreateLeafs;
+
/**
- * The ElementChange that describes the latest changes.
+ * Vector that contains all the edits. Maybe replace by a HashMap.
*/
- DefaultDocumentEvent documentEvent;
+ private ArrayList edits;
+
+ private boolean offsetLastIndex;
+ private boolean offsetLastIndexReplace;
/**
* Creates a new <code>ElementBuffer</code> for the specified
@@ -469,7 +544,6 @@ public class DefaultStyledDocument extends AbstractDocument implements
public ElementBuffer(Element root)
{
this.root = root;
- elementStack = new Stack();
}
/**
@@ -495,13 +569,9 @@ public class DefaultStyledDocument extends AbstractDocument implements
*/
public void remove(int offs, int len, DefaultDocumentEvent ev)
{
- if (len == 0)
- return;
- offset = offs;
- length = len;
- pos = offset;
- documentEvent = ev;
+ prepareEdit(offs, len);
removeUpdate();
+ finishEdit(ev);
}
/**
@@ -511,109 +581,241 @@ public class DefaultStyledDocument extends AbstractDocument implements
*/
protected void removeUpdate()
{
- int startParagraph = root.getElementIndex(offset);
- int endParagraph = root.getElementIndex(offset + length);
- Element[] empty = new Element[0];
- int removeStart = -1;
- int removeEnd = -1;
- for (int i = startParagraph; i < endParagraph; i++)
+ removeElements(root, offset, endOffset);
+ }
+
+ private boolean removeElements(Element elem, int rmOffs0, int rmOffs1)
+ {
+ boolean ret = false;
+ if (! elem.isLeaf())
{
- BranchElement paragraph = (BranchElement) root.getElement(i);
- int contentStart = paragraph.getElementIndex(offset);
- int contentEnd = paragraph.getElementIndex(offset + length);
- if (contentStart == paragraph.getStartOffset()
- && contentEnd == paragraph.getEndOffset())
+ // Update stack for changes.
+ int index0 = elem.getElementIndex(rmOffs0);
+ int index1 = elem.getElementIndex(rmOffs1);
+ elementStack.push(new Edit(elem, index0));
+ Edit ec = (Edit) elementStack.peek();
+
+ // If the range is contained by one element,
+ // we just forward the request
+ if (index0 == index1)
{
- // In this case we only need to remove the whole paragraph. We
- // do this in one go after this loop and only record the indices
- // here.
- if (removeStart == -1)
+ Element child0 = elem.getElement(index0);
+ if(rmOffs0 <= child0.getStartOffset()
+ && rmOffs1 >= child0.getEndOffset())
{
- removeStart = i;
- removeEnd = i;
+ // Element totally removed.
+ ec.removed.add(child0);
+ }
+ else if (removeElements(child0, rmOffs0, rmOffs1))
+ {
+ ec.removed.add(child0);
}
- else
- removeEnd = i;
}
else
{
- // In this case we remove a couple of child elements from this
- // paragraph.
- int removeLen = contentEnd - contentStart;
- Element[] removed = new Element[removeLen];
- for (int j = contentStart; j < contentEnd; j++)
- removed[j] = paragraph.getElement(j);
- Edit edit = getEditForParagraphAndIndex(paragraph, contentStart);
- edit.addRemovedElements(removed);
+ // The removal range spans elements. If we can join
+ // the two endpoints, do it. Otherwise we remove the
+ // interior and forward to the endpoints.
+ Element child0 = elem.getElement(index0);
+ Element child1 = elem.getElement(index1);
+ boolean containsOffs1 = (rmOffs1 < elem.getEndOffset());
+ if (containsOffs1 && canJoin(child0, child1))
+ {
+ // Remove and join.
+ for (int i = index0; i <= index1; i++)
+ {
+ ec.removed.add(elem.getElement(i));
+ }
+ Element e = join(elem, child0, child1, rmOffs0, rmOffs1);
+ ec.added.add(e);
+ }
+ else
+ {
+ // Remove interior and forward.
+ int rmIndex0 = index0 + 1;
+ int rmIndex1 = index1 - 1;
+ if (child0.getStartOffset() == rmOffs0
+ || (index0 == 0 && child0.getStartOffset() > rmOffs0
+ && child0.getEndOffset() <= rmOffs1))
+ {
+ // Start element completely consumed.
+ child0 = null;
+ rmIndex0 = index0;
+ }
+ if (! containsOffs1)
+ {
+ child1 = null;
+ rmIndex1++;
+ }
+ else if (child1.getStartOffset() == rmOffs1)
+ {
+ // End element not touched.
+ child1 = null;
+ }
+ if (rmIndex0 <= rmIndex1)
+ {
+ ec.index = rmIndex0;
+ }
+ for (int i = rmIndex0; i <= rmIndex1; i++)
+ {
+ ec.removed.add(elem.getElement(i));
+ }
+ if (child0 != null)
+ {
+ if(removeElements(child0, rmOffs0, rmOffs1))
+ {
+ ec.removed.add(0, child0);
+ ec.index = index0;
+ }
+ }
+ if (child1 != null)
+ {
+ if(removeElements(child1, rmOffs0, rmOffs1))
+ {
+ ec.removed.add(child1);
+ }
+ }
}
+ }
+
+ // Perform changes.
+ pop();
+
+ // Return true if we no longer have any children.
+ if(elem.getElementCount() == (ec.removed.size() - ec.added.size()))
+ ret = true;
}
- // Now we remove paragraphs from the root that have been tagged for
- // removal.
- if (removeStart != -1)
+ return ret;
+ }
+
+ private boolean canJoin(Element e0, Element e1)
+ {
+ boolean ret = false;
+ if ((e0 != null) && (e1 != null))
{
- int removeLen = removeEnd - removeStart;
- Element[] removed = new Element[removeLen];
- for (int i = removeStart; i < removeEnd; i++)
- removed[i] = root.getElement(i);
- Edit edit = getEditForParagraphAndIndex((BranchElement) root,
- removeStart);
- edit.addRemovedElements(removed);
+ // Don't join a leaf to a branch.
+ boolean isLeaf0 = e0.isLeaf();
+ boolean isLeaf1 = e1.isLeaf();
+ if(isLeaf0 == isLeaf1)
+ {
+ if (isLeaf0)
+ {
+ // Only join leaves if the attributes match, otherwise
+ // style information will be lost.
+ ret = e0.getAttributes().isEqual(e1.getAttributes());
+ }
+ else
+ {
+ // Only join non-leafs if the names are equal. This may result
+ // in loss of style information, but this is typically
+ // acceptable for non-leafs.
+ String name0 = e0.getName();
+ String name1 = e1.getName();
+ if (name0 != null)
+ ret = name0.equals(name1);
+ else if (name1 != null)
+ ret = name1.equals(name0);
+ else // Both names null.
+ ret = true;
+ }
+ }
}
+ return ret;
}
- /**
- * Performs the actual work for {@link #change}. The elements at the
- * interval boundaries are split up (if necessary) so that the interval
- * boundaries are located at element boundaries.
- */
- protected void changeUpdate()
+ private Element join(Element p, Element left, Element right, int rmOffs0,
+ int rmOffs1)
{
- // Split up the element at the start offset if necessary.
- Element el = getCharacterElement(offset);
- Element[] res = split(el, offset, 0, el.getElementIndex(offset));
- BranchElement par = (BranchElement) el.getParentElement();
- int index = par.getElementIndex(offset);
- Edit edit = getEditForParagraphAndIndex(par, index);
- if (res[1] != null)
+ Element joined = null;
+ if (left.isLeaf() && right.isLeaf())
+ {
+ joined = createLeafElement(p, left.getAttributes(),
+ left.getStartOffset(),
+ right.getEndOffset());
+ }
+ else if ((! left.isLeaf()) && (! right.isLeaf()))
{
- Element[] removed;
- Element[] added;
- if (res[0] == null)
+ // Join two branch elements. This copies the children before
+ // the removal range on the left element, and after the removal
+ // range on the right element. The two elements on the edge
+ // are joined if possible and needed.
+ joined = createBranchElement(p, left.getAttributes());
+ int ljIndex = left.getElementIndex(rmOffs0);
+ int rjIndex = right.getElementIndex(rmOffs1);
+ Element lj = left.getElement(ljIndex);
+ if (lj.getStartOffset() >= rmOffs0)
+ {
+ lj = null;
+ }
+ Element rj = right.getElement(rjIndex);
+ if (rj.getStartOffset() == rmOffs1)
+ {
+ rj = null;
+ }
+ ArrayList children = new ArrayList();
+ // Transfer the left.
+ for (int i = 0; i < ljIndex; i++)
+ {
+ children.add(clone(joined, left.getElement(i)));
+ }
+
+ // Transfer the join/middle.
+ if (canJoin(lj, rj))
{
- removed = new Element[0];
- added = new Element[] { res[1] };
- index++;
+ Element e = join(joined, lj, rj, rmOffs0, rmOffs1);
+ children.add(e);
}
else
{
- removed = new Element[] { el };
- added = new Element[] { res[0], res[1] };
+ if (lj != null)
+ {
+ children.add(cloneAsNecessary(joined, lj, rmOffs0, rmOffs1));
+ }
+ if (rj != null)
+ {
+ children.add(cloneAsNecessary(joined, rj, rmOffs0, rmOffs1));
+ }
+ }
+
+ // Transfer the right.
+ int n = right.getElementCount();
+ for (int i = (rj == null) ? rjIndex : rjIndex + 1; i < n; i++)
+ {
+ children.add(clone(joined, right.getElement(i)));
}
- edit.addRemovedElements(removed);
- edit.addAddedElements(added);
+ // Install the children.
+ Element[] c = new Element[children.size()];
+ c = (Element[]) children.toArray(c);
+ ((BranchElement) joined).replace(0, 0, c);
+ }
+ else
+ {
+ assert false : "Must not happen";
}
+ return joined;
+ }
- int endOffset = offset + length;
- el = getCharacterElement(endOffset);
- res = split(el, endOffset, 0, el.getElementIndex(endOffset));
- par = (BranchElement) el.getParentElement();
- if (res[0] != null)
+ /**
+ * Performs the actual work for {@link #change}. The elements at the
+ * interval boundaries are split up (if necessary) so that the interval
+ * boundaries are located at element boundaries.
+ */
+ protected void changeUpdate()
+ {
+ boolean didEnd = split(offset, length);
+ if (! didEnd)
{
- Element[] removed;
- Element[] added;
- if (res[1] == null)
- {
- removed = new Element[0];
- added = new Element[] { res[1] };
- }
- else
+ // need to do the other end
+ while (elementStack.size() != 0)
{
- removed = new Element[] { el };
- added = new Element[] { res[0], res[1] };
+ pop();
}
- edit.addRemovedElements(removed);
- edit.addAddedElements(added);
+ split(offset + length, 0);
+ }
+ while (elementStack.size() != 0)
+ {
+ pop();
}
}
@@ -683,6 +885,39 @@ public class DefaultStyledDocument extends AbstractDocument implements
return clone;
}
+ private Element cloneAsNecessary(Element parent, Element clonee,
+ int rmOffs0, int rmOffs1)
+ {
+ Element cloned;
+ if (clonee.isLeaf())
+ {
+ cloned = createLeafElement(parent, clonee.getAttributes(),
+ clonee.getStartOffset(),
+ clonee.getEndOffset());
+ }
+ else
+ {
+ Element e = createBranchElement(parent, clonee.getAttributes());
+ int n = clonee.getElementCount();
+ ArrayList childrenList = new ArrayList(n);
+ for (int i = 0; i < n; i++)
+ {
+ Element elem = clonee.getElement(i);
+ if (elem.getStartOffset() < rmOffs0
+ || elem.getEndOffset() > rmOffs1)
+ {
+ childrenList.add(cloneAsNecessary(e, elem, rmOffs0,
+ rmOffs1));
+ }
+ }
+ Element[] children = new Element[childrenList.size()];
+ children = (Element[]) childrenList.toArray(children);
+ ((BranchElement) e).replace(0, 0, children);
+ cloned = e;
+ }
+ return cloned;
+ }
+
/**
* Inserts new <code>Element</code> in the document at the specified
* position. Most of the work is done by {@link #insertUpdate}, after some
@@ -701,70 +936,98 @@ public class DefaultStyledDocument extends AbstractDocument implements
public void insert(int offset, int length, ElementSpec[] data,
DefaultDocumentEvent ev)
{
- if (length == 0)
- return;
-
+ if (length > 0)
+ {
+ prepareEdit(offset, length);
+ insertUpdate(data);
+ finishEdit(ev);
+ }
+ }
+
+ /**
+ * Prepares the state of this object for performing an insert.
+ *
+ * @param offset the offset at which is inserted
+ * @param length the length of the inserted region
+ */
+ private void prepareEdit(int offset, int length)
+ {
this.offset = offset;
this.pos = offset;
this.endOffset = offset + length;
this.length = length;
- documentEvent = ev;
-
- edits.removeAllElements();
- elementStack.removeAllElements();
- lastFractured = null;
- fracNotCreated = false;
- insertUpdate(data);
+
+ if (edits == null)
+ edits = new ArrayList();
+ else
+ edits.clear();
+
+ if (elementStack == null)
+ elementStack = new Stack();
+ else
+ elementStack.clear();
+
+ fracturedParent = null;
+ fracturedChild = null;
+ offsetLastIndex = false;
+ offsetLastIndexReplace = false;
+ }
+
+ /**
+ * Finishes an insert. This applies all changes and updates
+ * the DocumentEvent.
+ *
+ * @param ev the document event
+ */
+ private void finishEdit(DefaultDocumentEvent ev)
+ {
// This for loop applies all the changes that were made and updates the
// DocumentEvent.
- int size = edits.size();
- for (int i = 0; i < size; i++)
- {
- Edit curr = (Edit) edits.get(i);
- BranchElement e = (BranchElement) curr.e;
- Element[] removed = curr.getRemovedElements();
- Element[] added = curr.getAddedElements();
- // FIXME: We probably shouldn't create the empty Element[] in the
- // first place.
- if (removed.length > 0 || added.length > 0)
- {
- if (curr.index + removed.length <= e.getElementCount())
- {
- e.replace(curr.index, removed.length, added);
- ElementEdit ee = new ElementEdit(e, curr.index, removed, added);
- ev.addEdit(ee);
- }
- else
- {
- System.err.println("WARNING: Tried to replace elements ");
- System.err.print("beyond boundaries: elementCount: ");
- System.err.println(e.getElementCount());
- System.err.print("index: " + curr.index);
- System.err.println(", removed.length: " + removed.length);
- }
- }
- }
+ for (Iterator i = edits.iterator(); i.hasNext();)
+ {
+ Edit edits = (Edit) i.next();
+ Element[] removed = new Element[edits.removed.size()];
+ removed = (Element[]) edits.removed.toArray(removed);
+ Element[] added = new Element[edits.added.size()];
+ added = (Element[]) edits.added.toArray(added);
+ int index = edits.index;
+ BranchElement parent = (BranchElement) edits.e;
+ parent.replace(index, removed.length, added);
+ ElementEdit ee = new ElementEdit(parent, index, removed, added);
+ ev.addEdit(ee);
+ }
}
/**
- * Inserts new content
+ * Inserts new content.
*
- * @param data
- * the element specifications for the elements to be inserted
+ * @param data the element specifications for the elements to be inserted
*/
protected void insertUpdate(ElementSpec[] data)
{
- // Push the root and the paragraph at offset onto the element stack.
+ // Push the current path to the stack.
Element current = root;
- int index;
- while (!current.isLeaf())
+ int index = current.getElementIndex(offset);
+ while (! current.isLeaf())
{
+ Element child = current.getElement(index);
+ int editIndex = child.isLeaf() ? index : index + 1;
+ Edit edit = new Edit(current, editIndex);
+ elementStack.push(edit);
+ current = child;
index = current.getElementIndex(offset);
- elementStack.push(current);
- current = current.getElement(index);
}
-
+
+ // Create a copy of the original path.
+ insertPath = new Edit[elementStack.size()];
+ insertPath = (Edit[]) elementStack.toArray(insertPath);
+
+ // No fracture yet.
+ createdFracture = false;
+
+ // Insert first content tag.
int i = 0;
+ recreateLeafs = false;
int type = data[0].getType();
if (type == ElementSpec.ContentType)
{
@@ -784,123 +1047,129 @@ public class DefaultStyledDocument extends AbstractDocument implements
// Handle each ElementSpec individually.
for (; i < data.length; i++)
{
- BranchElement paragraph = (BranchElement) elementStack.peek();
- switch (data[i].getType())
+ insertElement(data[i]);
+ }
+
+ // Fracture if we haven't done yet.
+ if (! createdFracture)
+ fracture(-1);
+
+ // Pop the remaining stack.
+ while (elementStack.size() != 0)
+ pop();
+
+ // Offset last index if necessary.
+ if (offsetLastIndex && offsetLastIndexReplace)
+ insertPath[insertPath.length - 1].index++;
+
+ // Make sure we havea an Edit for each path item that has a change.
+ for (int p = insertPath.length - 1; p >= 0; p--)
+ {
+ Edit edit = insertPath[p];
+ if (edit.e == fracturedParent)
+ edit.added.add(fracturedChild);
+ if ((edit.added.size() > 0 || edit.removed.size() > 0)
+ && ! edits.contains(edit))
+ edits.add(edit);
+ }
+
+ // Remove element that would be created by an insert at 0 with
+ // an initial end tag.
+ if (offset == 0 && fracturedParent != null
+ && data[0].getType() == ElementSpec.EndTagType)
+ {
+ for (int p = 0;
+ p < data.length && data[p].getType() == ElementSpec.EndTagType;
+ p++)
{
- case ElementSpec.StartTagType:
- switch (data[i].getDirection())
- {
- case ElementSpec.JoinFractureDirection:
- // Fracture the tree and ensure the appropriate element
- // is on top of the stack.
- fracNotCreated = false;
- insertFracture(data[i]);
- if (fracNotCreated)
- {
- if (lastFractured != null)
- elementStack.push(lastFractured.getParentElement());
- else
- elementStack.push(paragraph.getElement(0));
- }
- break;
- case ElementSpec.JoinNextDirection:
- // Push the next paragraph element onto the stack so
- // future insertions are added to it.
- int ix = paragraph.getElementIndex(pos) + 1;
- elementStack.push(paragraph.getElement(ix));
- break;
- default:
- Element br = null;
- if (data.length > i + 1)
- {
- // leaves will be added to paragraph later
- int x = 0;
- if (paragraph.getElementCount() > 0)
- x = paragraph.getElementIndex(pos) + 1;
- Edit e = getEditForParagraphAndIndex(paragraph, x);
- br = (BranchElement) createBranchElement(paragraph,
- data[i].getAttributes());
- e.added.add(br);
- elementStack.push(br);
- }
- else
- // need to add leaves to paragraph now
- br = insertParagraph(paragraph, pos);
- break;
- }
- break;
- case ElementSpec.EndTagType:
- elementStack.pop();
- break;
- case ElementSpec.ContentType:
- insertContentTag(data[i]);
- offset = pos;
- break;
+ Edit edit = insertPath[insertPath.length - p - 1];
+ edit.index--;
+ edit.removed.add(0, edit.e.getElement(edit.index));
}
}
}
-
- /**
- * Inserts a new paragraph.
- *
- * @param par -
- * the parent
- * @param offset -
- * the offset
- * @return the new paragraph
- */
- private Element insertParagraph(BranchElement par, int offset)
+
+ private void pop()
+ {
+ Edit edit = (Edit) elementStack.peek();
+ elementStack.pop();
+ if ((edit.added.size() > 0) || (edit.removed.size() > 0))
+ {
+ edits.add(edit);
+ }
+ else if (! elementStack.isEmpty())
+ {
+ Element e = edit.e;
+ if (e.getElementCount() == 0)
+ {
+ // If we pushed a branch element that didn't get
+ // used, make sure its not marked as having been added.
+ edit = (Edit) elementStack.peek();
+ edit.added.remove(e);
+ }
+ }
+ }
+
+ private void insertElement(ElementSpec spec)
{
- int index = par.getElementIndex(offset);
- Element current = par.getElement(index);
- Element[] res = split(current, offset, 0, 0);
- Edit e = getEditForParagraphAndIndex(par, index + 1);
- Element ret;
- if (res[1] != null)
+ Edit edit = (Edit) elementStack.peek();
+ switch (spec.getType())
{
- Element[] removed;
- Element[] added;
- if (res[0] == null)
+ case ElementSpec.StartTagType:
+ switch (spec.getDirection())
{
- removed = new Element[0];
- if (res[1] instanceof BranchElement)
+ case ElementSpec.JoinFractureDirection:
+ // Fracture the tree and ensure the appropriate element
+ // is on top of the stack.
+ if (! createdFracture)
{
- added = new Element[] { res[1] };
- ret = res[1];
+ fracture(elementStack.size() - 1);
}
- else
+ if (! edit.isFracture)
{
- ret = createBranchElement(par, null);
- added = new Element[] { ret, res[1] };
+ // If the parent isn't a fracture, then the fracture is
+ // in fracturedChild.
+ Edit newEdit = new Edit(fracturedChild, 0, true);
+ elementStack.push(newEdit);
}
- index++;
- }
- else
- {
- removed = new Element[] { current };
- if (res[1] instanceof BranchElement)
+ else
{
- ret = res[1];
- added = new Element[] { res[0], res[1] };
+ // Otherwise use the parent's first child.
+ Element el = edit.e.getElement(0);
+ Edit newEdit = new Edit(el, 0, true);
+ elementStack.push(newEdit);
}
- else
+ break;
+ case ElementSpec.JoinNextDirection:
+ // Push the next paragraph element onto the stack so
+ // future insertions are added to it.
+ Element parent = edit.e.getElement(edit.index);
+ if (parent.isLeaf())
{
- ret = createBranchElement(par, null);
- added = new Element[] { res[0], ret, res[1] };
+ if (edit.index + 1 < edit.e.getElementCount())
+ parent = edit.e.getElement(edit.index + 1);
+ else
+ assert false; // Must not happen.
}
+ elementStack.push(new Edit(parent, 0, true));
+ break;
+ default:
+ Element branch = createBranchElement(edit.e,
+ spec.getAttributes());
+ edit.added.add(branch);
+ elementStack.push(new Edit(branch, 0));
+ break;
}
-
- e.addAddedElements(added);
- e.addRemovedElements(removed);
- }
- else
- {
- ret = createBranchElement(par, null);
- e.addAddedElement(ret);
+ break;
+ case ElementSpec.EndTagType:
+ pop();
+ break;
+ case ElementSpec.ContentType:
+ insertContentTag(spec, edit);
+ break;
}
- return ret;
}
-
+
/**
* Inserts the first tag into the document.
*
@@ -910,67 +1179,71 @@ public class DefaultStyledDocument extends AbstractDocument implements
private void insertFirstContentTag(ElementSpec[] data)
{
ElementSpec first = data[0];
- BranchElement paragraph = (BranchElement) elementStack.peek();
- int index = paragraph.getElementIndex(pos);
- Element current = paragraph.getElement(index);
- int newEndOffset = pos + first.length;
+ Edit edit = (Edit) elementStack.peek();
+ Element current = edit.e.getElement(edit.index);
+ int firstEndOffset = offset + first.length;
boolean onlyContent = data.length == 1;
- Edit edit = getEditForParagraphAndIndex(paragraph, index);
switch (first.getDirection())
{
case ElementSpec.JoinPreviousDirection:
- if (current.getEndOffset() != newEndOffset && !onlyContent)
+ if (current.getEndOffset() != firstEndOffset && ! onlyContent)
{
- Element newEl1 = createLeafElement(paragraph,
+ Element newEl1 = createLeafElement(edit.e,
current.getAttributes(),
current.getStartOffset(),
- newEndOffset);
- edit.addAddedElement(newEl1);
- edit.addRemovedElement(current);
- offset = newEndOffset;
+ firstEndOffset);
+ edit.added.add(newEl1);
+ edit.removed.add(current);
+ if (current.getEndOffset() != endOffset)
+ recreateLeafs = true;
+ else
+ offsetLastIndex = true;
+ }
+ else
+ {
+ offsetLastIndex = true;
+ offsetLastIndexReplace = true;
}
break;
case ElementSpec.JoinNextDirection:
- if (pos != 0)
+ if (offset != 0)
{
- Element newEl1 = createLeafElement(paragraph,
+ Element newEl1 = createLeafElement(edit.e,
current.getAttributes(),
current.getStartOffset(),
- pos);
- edit.addAddedElement(newEl1);
- Element next = paragraph.getElement(index + 1);
-
+ offset);
+ edit.added.add(newEl1);
+ Element next = edit.e.getElement(edit.index + 1);
if (onlyContent)
- newEl1 = createLeafElement(paragraph, next.getAttributes(),
- pos, next.getEndOffset());
+ newEl1 = createLeafElement(edit.e, next.getAttributes(),
+ offset, next.getEndOffset());
else
{
- newEl1 = createLeafElement(paragraph, next.getAttributes(),
- pos, newEndOffset);
- pos = newEndOffset;
+ newEl1 = createLeafElement(edit.e, next.getAttributes(),
+ offset, firstEndOffset);
}
- edit.addAddedElement(newEl1);
- edit.addRemovedElement(current);
- edit.addRemovedElement(next);
+ edit.added.add(newEl1);
+ edit.removed.add(current);
+ edit.removed.add(next);
}
break;
- default:
- if (current.getStartOffset() != pos)
+ default: // OriginateDirection.
+ if (current.getStartOffset() != offset)
{
- Element newEl = createLeafElement(paragraph,
+ Element newEl = createLeafElement(edit.e,
current.getAttributes(),
current.getStartOffset(),
- pos);
- edit.addAddedElement(newEl);
+ offset);
+ edit.added.add(newEl);
}
- edit.addRemovedElement(current);
- Element newEl1 = createLeafElement(paragraph, first.getAttributes(),
- pos, newEndOffset);
- edit.addAddedElement(newEl1);
+ edit.removed.add(current);
+ Element newEl1 = createLeafElement(edit.e, first.getAttributes(),
+ offset, firstEndOffset);
+ edit.added.add(newEl1);
if (current.getEndOffset() != endOffset)
- recreateLeaves(newEndOffset, paragraph, onlyContent);
+ recreateLeafs = true;
else
- offset = newEndOffset;
+ offsetLastIndex = true;
break;
}
}
@@ -981,391 +1254,353 @@ public class DefaultStyledDocument extends AbstractDocument implements
* @param tag -
* the element spec
*/
- private void insertContentTag(ElementSpec tag)
+ private void insertContentTag(ElementSpec tag, Edit edit)
{
- BranchElement paragraph = (BranchElement) elementStack.peek();
int len = tag.getLength();
int dir = tag.getDirection();
AttributeSet tagAtts = tag.getAttributes();
if (dir == ElementSpec.JoinNextDirection)
{
- int index = paragraph.getElementIndex(pos);
- Element target = paragraph.getElement(index);
- Edit edit = getEditForParagraphAndIndex(paragraph, index);
-
- if (paragraph.getStartOffset() > pos)
- {
- Element first = paragraph.getElement(0);
- Element newEl = createLeafElement(paragraph,
- first.getAttributes(), pos,
- first.getEndOffset());
- edit.addAddedElement(newEl);
- edit.addRemovedElement(first);
- }
- else if (paragraph.getElementCount() > (index + 1)
- && (pos == target.getStartOffset() && !target.equals(lastFractured)))
+ if (! edit.isFracture)
{
- Element next = paragraph.getElement(index + 1);
- Element newEl = createLeafElement(paragraph,
- next.getAttributes(), pos,
- next.getEndOffset());
- edit.addAddedElement(newEl);
- edit.addRemovedElement(next);
- edit.addRemovedElement(target);
+ Element first = null;
+ if (insertPath != null)
+ {
+ for (int p = insertPath.length - 1; p >= 0; p--)
+ {
+ if (insertPath[p] == edit)
+ {
+ if (p != insertPath.length - 1)
+ first = edit.e.getElement(edit.index);
+ break;
+ }
+ }
+ }
+ if (first == null)
+ first = edit.e.getElement(edit.index + 1);
+ Element leaf = createLeafElement(edit.e, first.getAttributes(),
+ pos, first.getEndOffset());
+ edit.added.add(leaf);
+ edit.removed.add(first);
}
else
{
- BranchElement parent = (BranchElement) paragraph.getParentElement();
- int i = parent.getElementIndex(pos);
- BranchElement next = (BranchElement) parent.getElement(i + 1);
- AttributeSet atts = tag.getAttributes();
-
- if (next != null)
- {
- Element nextLeaf = next.getElement(0);
- Edit e = getEditForParagraphAndIndex(next, 0);
- Element newEl2 = createLeafElement(next, atts, pos, nextLeaf.getEndOffset());
- e.addAddedElement(newEl2);
- e.addRemovedElement(nextLeaf);
- }
+ Element first = edit.e.getElement(0);
+ Element leaf = createLeafElement(edit.e, first.getAttributes(),
+ pos, first.getEndOffset());
+ edit.added.add(leaf);
+ edit.removed.add(first);
}
}
else
{
- int end = pos + len;
- Element leaf = createLeafElement(paragraph, tag.getAttributes(), pos, end);
-
- // Check for overlap with other leaves/branches
- if (paragraph.getElementCount() > 0)
- {
- int index = paragraph.getElementIndex(pos);
- Element target = paragraph.getElement(index);
- boolean onlyContent = target.isLeaf();
-
- BranchElement toRec = paragraph;
- if (!onlyContent)
- toRec = (BranchElement) target;
-
- // Check if we should place the leaf before or after target
- if (pos > target.getStartOffset())
- index++;
-
- Edit edit = getEditForParagraphAndIndex(paragraph, index);
- edit.addAddedElement(leaf);
- }
- else
- paragraph.replace(0, 0, new Element[] { leaf });
+ Element leaf = createLeafElement(edit.e, tag.getAttributes(), pos,
+ pos + len);
+ edit.added.add(leaf);
}
-
+
pos += len;
+
}
/**
- * This method fractures the child at offset.
+ * This method fractures bottomost leaf in the elementStack. This
+ * happens when the first inserted tag is not content.
*
* @param data
* the ElementSpecs used for the entire insertion
*/
private void createFracture(ElementSpec[] data)
{
- BranchElement paragraph = (BranchElement) elementStack.peek();
- int index = paragraph.getElementIndex(offset);
- Element child = paragraph.getElement(index);
- Edit edit = getEditForParagraphAndIndex(paragraph, index);
- AttributeSet atts = child.getAttributes();
-
+ Edit edit = (Edit) elementStack.peek();
+ Element child = edit.e.getElement(edit.index);
if (offset != 0)
{
- Element newEl1 = createLeafElement(paragraph, atts,
- child.getStartOffset(), offset);
- edit.addAddedElement(newEl1);
- edit.addRemovedElement(child);
+ Element newChild = createLeafElement(edit.e, child.getAttributes(),
+ child.getStartOffset(), offset);
+ edit.added.add(newChild);
}
+ edit.removed.add(child);
+ if (child.getEndOffset() != endOffset)
+ recreateLeafs = true;
+ else
+ offsetLastIndex = true;
}
- /**
- * Recreates a specified part of a the tree after a new leaf
- * has been inserted.
- *
- * @param start - where to start recreating from
- * @param paragraph - the paragraph to recreate
- * @param onlyContent - true if this is the only content
- */
- private void recreateLeaves(int start, BranchElement paragraph, boolean onlyContent)
+ private void fracture(int depth)
{
- int index = paragraph.getElementIndex(start);
- Element child = paragraph.getElement(index);
- AttributeSet atts = child.getAttributes();
-
- if (!onlyContent)
+ int len = insertPath.length;
+ int lastIndex = -1;
+ boolean recreate = recreateLeafs;
+ Edit lastEdit = insertPath[len - 1];
+ boolean childChanged = lastEdit.index + 1 < lastEdit.e.getElementCount();
+ int deepestChangedIndex = recreate ? len : - 1;
+ int lastChangedIndex = len - 1;
+ createdFracture = true;
+ for (int i = len - 2; i >= 0; i--)
{
- BranchElement newBranch = (BranchElement) createBranchElement(paragraph,
- atts);
- Element newLeaf = createLeafElement(newBranch, atts, start,
- child.getEndOffset());
- newBranch.replace(0, 0, new Element[] { newLeaf });
-
- BranchElement parent = (BranchElement) paragraph.getParentElement();
- int parSize = parent.getElementCount();
- Edit edit = getEditForParagraphAndIndex(parent, parSize);
- edit.addAddedElement(newBranch);
-
- int paragraphSize = paragraph.getElementCount();
- Element[] removed = new Element[paragraphSize - (index + 1)];
- int s = 0;
- for (int j = index + 1; j < paragraphSize; j++)
- removed[s++] = paragraph.getElement(j);
-
- edit = getEditForParagraphAndIndex(paragraph, index);
- edit.addRemovedElements(removed);
- Element[] added = recreateAfterFracture(removed, newBranch, 0, child.getEndOffset());
- newBranch.replace(1, 0, added);
-
- lastFractured = newLeaf;
- pos = newBranch.getEndOffset();
+ Edit edit = insertPath[i];
+ if (edit.added.size() > 0 || i == depth)
+ {
+ lastIndex = i;
+ if (! recreate && childChanged)
+ {
+ recreate = true;
+ if (deepestChangedIndex == -1)
+ deepestChangedIndex = lastChangedIndex + 1;
+ }
+ }
+ if (! childChanged && edit.index < edit.e.getElementCount())
+ {
+ childChanged = true;
+ lastChangedIndex = i;
+ }
}
- else
+ if (recreate)
{
- Element newLeaf = createLeafElement(paragraph, atts, start,
- child.getEndOffset());
- Edit edit = getEditForParagraphAndIndex(paragraph, index);
- edit.addAddedElement(newLeaf);
+ if (lastIndex == -1)
+ lastIndex = len - 1;
+ recreate(lastIndex, deepestChangedIndex);
}
}
-
- /**
- * Splits an element if <code>offset</code> is not already at its
- * boundary.
- *
- * @param el
- * the Element to possibly split
- * @param offset
- * the offset at which to possibly split
- * @param space
- * the amount of space to create between the splitted parts
- * @param editIndex
- * the index of the edit to use
- * @return An array of elements which represent the split result. This array
- * has two elements, the two parts of the split. The first element
- * might be null, which means that the element which should be
- * splitted can remain in place. The second element might also be
- * null, which means that the offset is already at an element
- * boundary and the element doesn't need to be splitted.
- */
- private Element[] split(Element el, int offset, int space, int editIndex)
+
+ private void recreate(int startIndex, int endIndex)
{
- // If we are at an element boundary, then return an empty array.
- if ((offset == el.getStartOffset() || offset == el.getEndOffset())
- && space == 0 && el.isLeaf())
- return new Element[2];
-
- // If the element is an instance of BranchElement, then we
- // recursivly
- // call this method to perform the split.
- Element[] res = new Element[2];
- if (el instanceof BranchElement)
+ // Recreate the element representing the inserted index.
+ Edit edit = insertPath[startIndex];
+ Element child;
+ Element newChild;
+ int changeLength = insertPath.length;
+
+ if (startIndex + 1 == changeLength)
+ child = edit.e.getElement(edit.index);
+ else
+ child = edit.e.getElement(edit.index - 1);
+
+ if(child.isLeaf())
{
- int index = el.getElementIndex(offset);
- Element child = el.getElement(index);
- Element[] result = split(child, offset, space, editIndex);
- Element[] removed;
- Element[] added;
- Element[] newAdded;
-
- int count = el.getElementCount();
- if (result[1] != null)
- {
- // This is the case when we can keep the first element.
- if (result[0] == null)
- {
- removed = new Element[count - index - 1];
- newAdded = new Element[count - index - 1];
- added = new Element[] {};
+ newChild = createLeafElement(edit.e, child.getAttributes(),
+ Math.max(endOffset, child.getStartOffset()),
+ child.getEndOffset());
+ }
+ else
+ {
+ newChild = createBranchElement(edit.e, child.getAttributes());
+ }
+ fracturedParent = edit.e;
+ fracturedChild = newChild;
- }
- // This is the case when we may not keep the first
- // element.
+ // Recreate all the elements to the right of the insertion point.
+ Element parent = newChild;
+ while (++startIndex < endIndex)
+ {
+ boolean isEnd = (startIndex + 1) == endIndex;
+ boolean isEndLeaf = (startIndex + 1) == changeLength;
+
+ // Create the newChild, a duplicate of the elment at
+ // index. This isn't done if isEnd and offsetLastIndex are true
+ // indicating a join previous was done.
+ edit = insertPath[startIndex];
+
+ // Determine the child to duplicate, won't have to duplicate
+ // if at end of fracture, or offseting index.
+ if(isEnd)
+ {
+ if(offsetLastIndex || ! isEndLeaf)
+ child = null;
else
+ child = edit.e.getElement(edit.index);
+ }
+ else
+ {
+ child = edit.e.getElement(edit.index - 1);
+ }
+
+ // Duplicate it.
+ if(child != null)
+ {
+ if(child.isLeaf())
{
- removed = new Element[count - index];
- newAdded = new Element[count - index];
- added = new Element[] { result[0] };
+ newChild = createLeafElement(parent, child.getAttributes(),
+ Math.max(endOffset, child.getStartOffset()),
+ child.getEndOffset());
}
- newAdded[0] = result[1];
- for (int i = index; i < count; i++)
+ else
{
- Element el2 = el.getElement(i);
- int ind = i - count + removed.length;
- removed[ind] = el2;
- if (ind != 0)
- newAdded[ind] = el2;
+ newChild = createBranchElement(parent,
+ child.getAttributes());
}
-
- Edit edit = getEditForParagraphAndIndex((BranchElement) el, editIndex);
- edit.addRemovedElements(removed);
- edit.addAddedElements(added);
-
- BranchElement newPar =
- (BranchElement) createBranchElement(el.getParentElement(),
- el.getAttributes());
- newPar.replace(0, 0, newAdded);
- res = new Element[] { null, newPar };
}
else
- {
- removed = new Element[count - index];
- for (int i = index; i < count; ++i)
- removed[i - index] = el.getElement(i);
-
- Edit edit = getEditForParagraphAndIndex((BranchElement) el, editIndex);
- edit.addRemovedElements(removed);
-
- BranchElement newPar = (BranchElement) createBranchElement(el.getParentElement(),
- el.getAttributes());
- newPar.replace(0, 0, removed);
- res = new Element[] { null, newPar };
+ newChild = null;
+
+ // Recreate the remaining children (there may be none).
+ int childrenToMove = edit.e.getElementCount() - edit.index;
+ Element[] children;
+ int moveStartIndex;
+ int childStartIndex = 1;
+
+ if (newChild == null)
+ {
+ // Last part of fracture.
+ if (isEndLeaf)
+ {
+ childrenToMove--;
+ moveStartIndex = edit.index + 1;
+ }
+ else
+ {
+ moveStartIndex = edit.index;
+ }
+ childStartIndex = 0;
+ children = new Element[childrenToMove];
+ }
+ else
+ {
+ if (! isEnd)
+ {
+ // Branch.
+ childrenToMove++;
+ moveStartIndex = edit.index;
}
+ else
+ {
+ // Last leaf, need to recreate part of it.
+ moveStartIndex = edit.index + 1;
+ }
+ children = new Element[childrenToMove];
+ children[0] = newChild;
}
- else if (el instanceof LeafElement)
- {
- BranchElement par = (BranchElement) el.getParentElement();
- Element el1 = createLeafElement(par, el.getAttributes(),
- el.getStartOffset(), offset);
-
- Element el2 = createLeafElement(par, el.getAttributes(),
- offset + space,
- el.getEndOffset());
- res = new Element[] { el1, el2 };
- }
- return res;
+
+ for (int c = childStartIndex; c < childrenToMove; c++)
+ {
+ Element toMove = edit.e.getElement(moveStartIndex++);
+ children[c] = recreateFracturedElement(parent, toMove);
+ edit.removed.add(toMove);
+ }
+ ((BranchElement) parent).replace(0, 0, children);
+ parent = newChild;
+ }
+
}
- /**
- * Inserts a fracture into the document structure.
- *
- * @param tag -
- * the element spec.
- */
- private void insertFracture(ElementSpec tag)
+ private Element recreateFracturedElement(Element parent, Element toCopy)
{
- // insert the fracture at offset.
- BranchElement parent = (BranchElement) elementStack.peek();
- int parentIndex = parent.getElementIndex(pos);
- AttributeSet parentAtts = parent.getAttributes();
- Element toFracture = parent.getElement(parentIndex);
- int parSize = parent.getElementCount();
- Edit edit = getEditForParagraphAndIndex(parent, parentIndex);
- Element frac = toFracture;
- int leftIns = 0;
- int indexOfFrac = toFracture.getElementIndex(pos);
- int size = toFracture.getElementCount();
-
- // gets the leaf that falls along the fracture
- frac = toFracture.getElement(indexOfFrac);
- while (!frac.isLeaf())
- frac = frac.getElement(frac.getElementIndex(pos));
-
- AttributeSet atts = frac.getAttributes();
- int fracStart = frac.getStartOffset();
- int fracEnd = frac.getEndOffset();
- if (pos >= fracStart && pos < fracEnd)
+ Element recreated;
+ if(toCopy.isLeaf())
{
- // recreate left-side of branch and all its children before offset
- // add the fractured leaves to the right branch
- BranchElement rightBranch =
- (BranchElement) createBranchElement(parent, parentAtts);
-
- // Check if left branch has already been edited. If so, we only
- // need to create the right branch.
- BranchElement leftBranch = null;
- Element[] added = null;
- if (edit.added.size() > 0 || edit.removed.size() > 0)
+ recreated = createLeafElement(parent, toCopy.getAttributes(),
+ Math.max(toCopy.getStartOffset(), endOffset),
+ toCopy.getEndOffset());
+ }
+ else
+ {
+ Element newParent = createBranchElement(parent,
+ toCopy.getAttributes());
+ int childCount = toCopy.getElementCount();
+ Element[] newChildren = new Element[childCount];
+ for (int i = 0; i < childCount; i++)
{
- added = new Element[] { rightBranch };
-
- // don't try to remove left part of tree
- parentIndex++;
+ newChildren[i] = recreateFracturedElement(newParent,
+ toCopy.getElement(i));
}
- else
- {
- leftBranch =
- (BranchElement) createBranchElement(parent, parentAtts);
- added = new Element[] { leftBranch, rightBranch };
+ ((BranchElement) newParent).replace(0, 0, newChildren);
+ recreated = newParent;
+ }
+ return recreated;
+ }
- // add fracture to leftBranch
- if (fracStart != pos)
- {
- Element leftFracturedLeaf =
- createLeafElement(leftBranch, atts, fracStart, pos);
- leftBranch.replace(leftIns, 0,
- new Element[] { leftFracturedLeaf });
- }
- }
+ private boolean split(int offs, int len)
+ {
+ boolean splitEnd = false;
+ // Push the path to the stack.
+ Element e = root;
+ int index = e.getElementIndex(offs);
+ while (! e.isLeaf())
+ {
+ elementStack.push(new Edit(e, index));
+ e = e.getElement(index);
+ index = e.getElementIndex(offs);
+ }
- if (!toFracture.isLeaf())
+ Edit ec = (Edit) elementStack.peek();
+ Element child = ec.e.getElement(ec.index);
+ // Make sure there is something to do. If the
+ // offset is already at a boundary then there is
+ // nothing to do.
+ if (child.getStartOffset() < offs && offs < child.getEndOffset())
+ {
+ // We need to split, now see if the other end is within
+ // the same parent.
+ int index0 = ec.index;
+ int index1 = index0;
+ if (((offs + len) < ec.e.getEndOffset()) && (len != 0))
{
- // add all non-fracture elements to the branches
- if (indexOfFrac > 0 && leftBranch != null)
+ // It's a range split in the same parent.
+ index1 = ec.e.getElementIndex(offs+len);
+ if (index1 == index0)
{
- Element[] add = new Element[indexOfFrac];
- for (int i = 0; i < indexOfFrac; i++)
- add[i] = toFracture.getElement(i);
- leftIns = add.length;
- leftBranch.replace(0, 0, add);
+ // It's a three-way split.
+ ec.removed.add(child);
+ e = createLeafElement(ec.e, child.getAttributes(),
+ child.getStartOffset(), offs);
+ ec.added.add(e);
+ e = createLeafElement(ec.e, child.getAttributes(),
+ offs, offs + len);
+ ec.added.add(e);
+ e = createLeafElement(ec.e, child.getAttributes(),
+ offs + len, child.getEndOffset());
+ ec.added.add(e);
+ return true;
}
-
- int count = size - indexOfFrac - 1;
- if (count > 0)
+ else
{
- Element[] add = new Element[count];
- int j = 0;
- int i = indexOfFrac + 1;
- while (j < count)
- add[j++] = toFracture.getElement(i++);
- rightBranch.replace(0, 0, add);
+ child = ec.e.getElement(index1);
+ if ((offs + len) == child.getStartOffset())
+ {
+ // End is already on a boundary.
+ index1 = index0;
+ }
}
+ splitEnd = true;
}
-
- // add to fracture to rightBranch
- // Check if we can join the right frac leaf with the next leaf
- int rm = 0;
- int end = fracEnd;
- Element next = rightBranch.getElement(0);
- if (next != null && next.isLeaf()
- && next.getAttributes().isEqual(atts))
+
+ // Split the first location.
+ pos = offs;
+ child = ec.e.getElement(index0);
+ ec.removed.add(child);
+ e = createLeafElement(ec.e, child.getAttributes(),
+ child.getStartOffset(), pos);
+ ec.added.add(e);
+ e = createLeafElement(ec.e, child.getAttributes(),
+ pos, child.getEndOffset());
+ ec.added.add(e);
+
+ // Pick up things in the middle.
+ for (int i = index0 + 1; i < index1; i++)
{
- end = next.getEndOffset();
- rm = 1;
+ child = ec.e.getElement(i);
+ ec.removed.add(child);
+ ec.added.add(child);
}
- Element rightFracturedLeaf = createLeafElement(rightBranch, atts,
- pos, end);
- rightBranch.replace(0, rm, new Element[] { rightFracturedLeaf });
-
- // recreate those elements after parentIndex and add/remove all
- // new/old elements to parent
- int remove = parSize - parentIndex;
- Element[] removed = new Element[0];
- Element[] added2 = new Element[0];
- if (remove > 0)
+ if (index1 != index0)
{
- removed = new Element[remove];
- int s = 0;
- for (int j = parentIndex; j < parSize; j++)
- removed[s++] = parent.getElement(j);
- edit.addRemovedElements(removed);
- added2 = recreateAfterFracture(removed, parent, 1,
- rightBranch.getEndOffset());
+ child = ec.e.getElement(index1);
+ pos = offs + len;
+ ec.removed.add(child);
+ e = createLeafElement(ec.e, child.getAttributes(),
+ child.getStartOffset(), pos);
+ ec.added.add(e);
+ e = createLeafElement(ec.e, child.getAttributes(),
+ pos, child.getEndOffset());
+
+ ec.added.add(e);
}
-
- edit.addAddedElements(added);
- edit.addAddedElements(added2);
- elementStack.push(rightBranch);
- lastFractured = rightFracturedLeaf;
}
- else
- fracNotCreated = true;
+ return splitEnd;
+
}
/**
@@ -1420,190 +1655,6 @@ public class DefaultStyledDocument extends AbstractDocument implements
}
}
- /**
- * This method looks through the Vector of Edits to see if there is already an
- * Edit object associated with the given paragraph. If there is, then we
- * return it. Otherwise we create a new Edit object, add it to the vector, and
- * return it. Note: this method is package private to avoid accessors.
- *
- * @param index
- * the index associated with the Edit we want to create
- * @param para
- * the paragraph associated with the Edit we want
- * @return the found or created Edit object
- */
- Edit getEditForParagraphAndIndex(BranchElement para, int index)
- {
- Edit curr;
- int size = edits.size();
- for (int i = 0; i < size; i++)
- {
- curr = (Edit) edits.elementAt(i);
- if (curr.e.equals(para))
- return curr;
- }
- curr = new Edit(para, index, null, null);
- edits.add(curr);
-
- return curr;
- }
- /**
- * Instance of all editing information for an object in the Vector. This class
- * is used to add information to the DocumentEvent associated with an
- * insertion/removal/change as well as to store the changes that need to be
- * made so they can be made all at the same (appropriate) time.
- */
- class Edit
- {
- /** The element to edit . */
- Element e;
-
- /** The index of the change. */
- int index;
-
- /** The removed elements. */
- Vector removed = new Vector();
-
- /** The added elements. */
- Vector added = new Vector();
-
- /**
- * Return an array containing the Elements that have been removed from the
- * paragraph associated with this Edit.
- *
- * @return an array of removed Elements
- */
- public Element[] getRemovedElements()
- {
- int size = removed.size();
- Element[] removedElements = new Element[size];
- for (int i = 0; i < size; i++)
- removedElements[i] = (Element) removed.elementAt(i);
- return removedElements;
- }
-
- /**
- * Return an array containing the Elements that have been added to the
- * paragraph associated with this Edit.
- *
- * @return an array of added Elements
- */
- public Element[] getAddedElements()
- {
- int size = added.size();
- Element[] addedElements = new Element[size];
- for (int i = 0; i < size; i++)
- addedElements[i] = (Element) added.elementAt(i);
- return addedElements;
- }
-
- /**
- * Checks if e is already in the vector.
- *
- * @param e - the Element to look for
- * @param v - the vector to search
- * @return true if e is in v.
- */
- private boolean contains(Vector v, Element e)
- {
- if (e == null)
- return false;
-
- int i = v.size();
- for (int j = 0; j < i; j++)
- {
- Element e1 = (Element) v.get(j);
- if ((e1 != null) && (e1.getAttributes().isEqual(e.getAttributes()))
- && (e1.getName().equals(e.getName()))
- && (e1.getStartOffset() == e.getStartOffset())
- && (e1.getEndOffset() == e.getEndOffset())
- && (e1.getParentElement().equals(e.getParentElement()))
- && (e1.getElementCount() == e.getElementCount()))
- return true;
- }
- return false;
- }
-
- /**
- * Adds one Element to the vector of removed Elements.
- *
- * @param e
- * the Element to add
- */
- public void addRemovedElement(Element e)
- {
- if (!contains(removed, e))
- removed.add(e);
- }
-
- /**
- * Adds each Element in the given array to the vector of removed Elements
- *
- * @param e
- * the array containing the Elements to be added
- */
- public void addRemovedElements(Element[] e)
- {
- if (e == null || e.length == 0)
- return;
- for (int i = 0; i < e.length; i++)
- {
- if (!contains(removed, e[i]))
- removed.add(e[i]);
- }
- }
-
- /**
- * Adds one Element to the vector of added Elements.
- *
- * @param e
- * the Element to add
- */
- public void addAddedElement(Element e)
- {
- if (!contains(added, e))
- added.add(e);
- }
-
- /**
- * Adds each Element in the given array to the vector of added Elements.
- *
- * @param e
- * the array containing the Elements to be added
- */
- public void addAddedElements(Element[] e)
- {
- if (e == null || e.length == 0)
- return;
- for (int i = 0; i < e.length; i++)
- {
- if (!contains(added, e[i]))
- added.add(e[i]);
- }
- }
-
- /**
- * Creates a new Edit object with the given parameters
- *
- * @param e
- * the paragraph Element associated with this Edit
- * @param i
- * the index within the paragraph where changes are started
- * @param removed
- * an array containing Elements that should be removed from the
- * paragraph Element
- * @param added
- * an array containing Elements that should be added to the
- * paragraph Element
- */
- public Edit(Element e, int i, Element[] removed, Element[] added)
- {
- this.e = e;
- this.index = i;
- addRemovedElements(removed);
- addAddedElements(added);
- }
- }
/**
* An element type for sections. This is a simple BranchElement with a unique
@@ -1674,11 +1725,6 @@ public class DefaultStyledDocument extends AbstractDocument implements
private StyleChangeListener styleChangeListener;
/**
- * Vector that contains all the edits. Maybe replace by a HashMap.
- */
- Vector edits = new Vector();
-
- /**
* Creates a new <code>DefaultStyledDocument</code>.
*/
public DefaultStyledDocument()
@@ -2079,147 +2125,220 @@ public class DefaultStyledDocument extends AbstractDocument implements
*/
protected void insertUpdate(DefaultDocumentEvent ev, AttributeSet attr)
{
- super.insertUpdate(ev, attr);
- // If the attribute set is null, use an empty attribute set.
+ int offs = ev.getOffset();
+ int len = ev.getLength();
+ int endOffs = offs + len;
if (attr == null)
attr = SimpleAttributeSet.EMPTY;
- int offset = ev.getOffset();
- int length = ev.getLength();
- int endOffset = offset + length;
- AttributeSet paragraphAttributes = getParagraphElement(endOffset).getAttributes();
- Segment txt = new Segment();
+
+ // Paragraph attributes are fetched from the point _after_ the insertion.
+ Element paragraph = getParagraphElement(endOffs);
+ AttributeSet pAttr = paragraph.getAttributes();
+ // Character attributes are fetched from the actual insertion point.
+ Element paragraph2 = getParagraphElement(offs);
+ int contIndex = paragraph2.getElementIndex(offs);
+ Element content = paragraph2.getElement(contIndex);
+ AttributeSet cAttr = content.getAttributes();
+
+ boolean insertAtBoundary = content.getEndOffset() == endOffs;
try
{
- getText(offset, length, txt);
- }
- catch (BadLocationException ex)
- {
- AssertionError ae = new AssertionError("Unexpected bad location");
- ae.initCause(ex);
- throw ae;
- }
+ Segment s = new Segment();
+ ArrayList buf = new ArrayList();
+ ElementSpec lastStartTag = null;
+ boolean insertAfterNewline = false;
+ short lastStartDir = ElementSpec.OriginateDirection;
+
+ // Special handle if we are inserting after a newline.
+ if (offs > 0)
+ {
+ getText(offs - 1, 1, s);
+ if (s.array[s.offset] == '\n')
+ {
+ insertAfterNewline = true;
+ lastStartDir = insertAfterNewline(paragraph, paragraph2,
+ pAttr, buf, offs,
+ endOffs);
+ // Search last start tag.
+ for (int i = buf.size() - 1; i >= 0 && lastStartTag == null;
+ i--)
+ {
+ ElementSpec tag = (ElementSpec) buf.get(i);
+ if (tag.getType() == ElementSpec.StartTagType)
+ {
+ lastStartTag = tag;
+ }
+ }
+ }
- int len = 0;
- Vector specs = new Vector();
- ElementSpec finalStartTag = null;
- short finalStartDirection = ElementSpec.OriginateDirection;
- boolean prevCharWasNewline = false;
- Element prev = getCharacterElement(offset);
- Element next = getCharacterElement(endOffset);
- Element prevParagraph = getParagraphElement(offset);
- Element paragraph = getParagraphElement(endOffset);
+ }
- int segmentEnd = txt.offset + txt.count;
+ // If we are not inserting after a newline, the paragraph attributes
+ // come from the paragraph under the insertion point.
+ if (! insertAfterNewline)
+ pAttr = paragraph2.getAttributes();
- // Check to see if we're inserting immediately after a newline.
- if (offset > 0)
- {
- try
+ // Scan text and build up the specs.
+ getText(offs, len, s);
+ int end = s.offset + s.count;
+ int last = s.offset;
+ for (int i = s.offset; i < end; i++)
{
- String s = getText(offset - 1, 1);
- if (s.equals("\n"))
+ if (s.array[i] == '\n')
{
- finalStartDirection = handleInsertAfterNewline(specs, offset,
- endOffset,
- prevParagraph,
- paragraph,
- paragraphAttributes);
-
- prevCharWasNewline = true;
- // Find the final start tag from the ones just created.
- for (int i = 0; i < specs.size(); i++)
- if (((ElementSpec) specs.get(i)).getType() == ElementSpec.StartTagType)
- finalStartTag = (ElementSpec) specs.get(i);
+ int breakOffs = i + 1;
+ buf.add(new ElementSpec(attr, ElementSpec.ContentType,
+ breakOffs - last));
+ buf.add(new ElementSpec(null, ElementSpec.EndTagType));
+ lastStartTag = new ElementSpec(pAttr,
+ ElementSpec.StartTagType);
+ buf.add(lastStartTag);
+ last = breakOffs;
}
}
- catch (BadLocationException ble)
+
+ // Need to add a tailing content tag if we didn't finish at a boundary.
+ if (last < end)
{
- // This shouldn't happen.
- AssertionError ae = new AssertionError();
- ae.initCause(ble);
- throw ae;
+ buf.add(new ElementSpec(attr, ElementSpec.ContentType,
+ end - last));
}
- }
- for (int i = txt.offset; i < segmentEnd; ++i)
- {
- len++;
- if (txt.array[i] == '\n')
+ // Now we need to fix up the directions of the specs.
+ ElementSpec first = (ElementSpec) buf.get(0);
+ int doclen = getLength();
+
+ // Maybe join-previous the first tag if it is content and has
+ // the same attributes as the previous character run.
+ if (first.getType() == ElementSpec.ContentType && cAttr.isEqual(attr))
+ first.setDirection(ElementSpec.JoinPreviousDirection);
+
+ // Join-fracture or join-next the last start tag if necessary.
+ if (lastStartTag != null)
+ {
+ if (insertAfterNewline)
+ lastStartTag.setDirection(lastStartDir);
+ else if (paragraph2.getEndOffset() != endOffs)
+ lastStartTag.setDirection(ElementSpec.JoinFractureDirection);
+ else
+ {
+ Element par = paragraph2.getParentElement();
+ int par2Index = par.getElementIndex(offs);
+ if (par2Index + 1 < par.getElementCount()
+ && ! par.getElement(par2Index + 1).isLeaf())
+ lastStartTag.setDirection(ElementSpec.JoinNextDirection);
+ }
+ }
+
+ // Join-next last tag if possible.
+ if (insertAtBoundary && endOffs < doclen)
{
- // Add the ElementSpec for the content.
- specs.add(new ElementSpec(attr, ElementSpec.ContentType, len));
-
- // Add ElementSpecs for the newline.
- specs.add(new ElementSpec(null, ElementSpec.EndTagType));
- finalStartTag = new ElementSpec(paragraphAttributes,
- ElementSpec.StartTagType);
- specs.add(finalStartTag);
- len = 0;
+ ElementSpec lastTag = (ElementSpec) buf.get(buf.size() - 1);
+ if (lastTag.getType() == ElementSpec.ContentType
+ && ((lastStartTag == null
+ && (paragraph == paragraph2 || insertAfterNewline))
+ || (lastStartTag != null
+ && lastStartTag.getDirection() != ElementSpec.OriginateDirection)))
+ {
+ int nextIndex = paragraph.getElementIndex(endOffs);
+ Element nextRun = paragraph.getElement(nextIndex);
+ if (nextRun.isLeaf() && attr.isEqual(nextRun.getAttributes()))
+ lastTag.setDirection(ElementSpec.JoinNextDirection);
+ }
+ }
+
+ else if (! insertAtBoundary && lastStartTag != null
+ && lastStartTag.getDirection() == ElementSpec.JoinFractureDirection)
+ {
+ ElementSpec lastTag = (ElementSpec) buf.get(buf.size() - 1);
+ if (lastTag.getType() == ElementSpec.ContentType
+ && lastTag.getDirection() != ElementSpec.JoinPreviousDirection
+ && attr.isEqual(cAttr))
+ {
+ lastTag.setDirection(ElementSpec.JoinNextDirection);
+ }
}
- }
- // Create last element if last character hasn't been a newline.
- if (len > 0)
- specs.add(new ElementSpec(attr, ElementSpec.ContentType, len));
+ ElementSpec[] specs = new ElementSpec[buf.size()];
+ specs = (ElementSpec[]) buf.toArray(specs);
+ buffer.insert(offs, len, specs, ev);
+ }
+ catch (BadLocationException ex)
+ {
+ // Ignore this. Comment out for debugging.
+ ex.printStackTrace();
+ }
+ super.insertUpdate(ev, attr);
+ }
- // Set the direction of the last spec of type StartTagType.
- // If we are inserting after a newline then this value comes from
- // handleInsertAfterNewline.
- if (finalStartTag != null)
+ private short insertAfterNewline(Element par1, Element par2,
+ AttributeSet attr, ArrayList buf,
+ int offs, int endOffs)
+ {
+ short dir = 0;
+ if (par1.getParentElement() == par2.getParentElement())
{
- if (prevCharWasNewline)
- finalStartTag.setDirection(finalStartDirection);
- else if (prevParagraph.getEndOffset() != endOffset)
- finalStartTag.setDirection(ElementSpec.JoinFractureDirection);
+ ElementSpec tag = new ElementSpec(attr, ElementSpec.EndTagType);
+ buf.add(tag);
+ tag = new ElementSpec(attr, ElementSpec.StartTagType);
+ buf.add(tag);
+ if (par2.getEndOffset() != endOffs)
+ dir = ElementSpec.JoinFractureDirection;
else
{
- // If there is an element AFTER this one, then set the
- // direction to JoinNextDirection.
- Element parent = prevParagraph.getParentElement();
- int index = parent.getElementIndex(offset);
- if (index + 1 < parent.getElementCount()
- && !parent.getElement(index + 1).isLeaf())
- finalStartTag.setDirection(ElementSpec.JoinNextDirection);
+ Element par = par2.getParentElement();
+ if (par.getElementIndex(offs) + 1 < par.getElementCount())
+ dir = ElementSpec.JoinNextDirection;
}
}
-
- // If we are at the last index, then check if we could probably be
- // joined with the next element.
- // This means:
- // - we must be a ContentTag
- // - if there is a next Element, we must have the same attributes
- // - if there is no next Element, but one will be created,
- // we must have the same attributes as the higher-level run.
- ElementSpec last = (ElementSpec) specs.lastElement();
- if (last.getType() == ElementSpec.ContentType)
+ else
{
- Element currentRun = prevParagraph.getElement(prevParagraph.getElementIndex(offset));
- if (currentRun.getEndOffset() == endOffset)
+ // For text with more than 2 levels, find the common parent of
+ // par1 and par2.
+ ArrayList parentsLeft = new ArrayList();
+ ArrayList parentsRight = new ArrayList();
+ Element e = par2;
+ while (e != null)
{
- if (endOffset < getLength() && next.getAttributes().isEqual(attr)
- && last.getType() == ElementSpec.ContentType)
- last.setDirection(ElementSpec.JoinNextDirection);
+ parentsLeft.add(e);
+ e = e.getParentElement();
}
- else
+ e = par1;
+ int leftIndex = -1;
+ while (e != null && (leftIndex = parentsLeft.indexOf(e)) == 1)
+ {
+ parentsRight.add(e);
+ e = e.getParentElement();
+ }
+
+ if (e != null)
+
{
- if (finalStartTag != null
- && finalStartTag.getDirection() == ElementSpec.JoinFractureDirection
- && currentRun.getAttributes().isEqual(attr))
+ // e is now the common parent.
+ // Insert the end tags.
+ for (int c = 0; c < leftIndex; c++)
+ {
+ buf.add(new ElementSpec(null, ElementSpec.EndTagType));
+ }
+ // Insert the start tags.
+ for (int c = parentsRight.size() - 1; c >= 0; c--)
{
- last.setDirection(ElementSpec.JoinNextDirection);
+ Element el = (Element) parentsRight.get(c);
+ ElementSpec tag = new ElementSpec(el.getAttributes(),
+ ElementSpec.StartTagType);
+ if (c > 0)
+ tag.setDirection(ElementSpec.JoinNextDirection);
+ buf.add(tag);
}
+ if (parentsRight.size() > 0)
+ dir = ElementSpec.JoinNextDirection;
+ else
+ dir = ElementSpec.JoinFractureDirection;
}
+ else
+ assert false;
}
-
- // If we are at the first new element, then check if it could be
- // joined with the previous element.
- ElementSpec first = (ElementSpec) specs.firstElement();
- if (prev.getAttributes().isEqual(attr)
- && first.getType() == ElementSpec.ContentType)
- first.setDirection(ElementSpec.JoinPreviousDirection);
-
- ElementSpec[] elSpecs = (ElementSpec[]) specs.toArray(new ElementSpec[specs.size()]);
- buffer.insert(offset, length, elSpecs, ev);
+ return dir;
}
/**
diff --git a/javax/swing/text/EmptyAttributeSet.java b/javax/swing/text/EmptyAttributeSet.java
new file mode 100644
index 000000000..98fb8828c
--- /dev/null
+++ b/javax/swing/text/EmptyAttributeSet.java
@@ -0,0 +1,153 @@
+/* EmptyAttributeSet.java -- An empty attribute set
+ 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 javax.swing.text;
+
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+/**
+ * An immutable, empty attribute set.
+ *
+ * @see SimpleAttributeSet#EMPTY
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+final class EmptyAttributeSet
+ implements AttributeSet
+{
+
+ /**
+ * Always return false as this AttributeSet doesn't contain any attributes.
+ */
+ public boolean containsAttribute(Object name, Object value)
+ {
+ return false;
+ }
+
+ /**
+ * Return true only if the attributes argument also contains no attributes.
+ */
+ public boolean containsAttributes(AttributeSet attributes)
+ {
+ return attributes.getAttributeCount() == 0;
+ }
+
+ /**
+ * Return this, as this is immutable.
+ */
+ public AttributeSet copyAttributes()
+ {
+ return this;
+ }
+
+ /**
+ * Always return null as this AttributeSet doesn't contain any attributes.
+ */
+ public Object getAttribute(Object key)
+ {
+ return null;
+ }
+
+ /**
+ * Always return 0.
+ */
+ public int getAttributeCount()
+ {
+ return 0;
+ }
+
+ /**
+ * Returns an empty Enumeration.
+ */
+ public Enumeration getAttributeNames()
+ {
+ return new Enumeration()
+ {
+ public boolean hasMoreElements()
+ {
+ return false;
+ }
+
+ public Object nextElement()
+ {
+ throw new NoSuchElementException("No more elements");
+ }
+
+ };
+ }
+
+ /**
+ * Always return null as this has no resolve parent.
+ */
+ public AttributeSet getResolveParent()
+ {
+ return null;
+ }
+
+ /**
+ * Always return false as this AttributeSet doesn't contain any attributes.
+ */
+ public boolean isDefined(Object attrName)
+ {
+ return false;
+ }
+
+ /**
+ * Other attribute sets are equal if they are empty too.
+ */
+ public boolean isEqual(AttributeSet attr)
+ {
+ return attr.getAttributeCount() == 0;
+ }
+
+ /**
+ * Other objects are equal if it's the same instance as this, or if
+ * it's another attribute set without attributes.
+ */
+ public boolean equals(Object o)
+ {
+ boolean eq = o == this;
+ if (! eq)
+ {
+ eq = (o instanceof AttributeSet)
+ && ((AttributeSet) o).getAttributeCount() == 0;
+ }
+ return eq;
+ }
+}
diff --git a/javax/swing/text/FlowView.java b/javax/swing/text/FlowView.java
index 89fcc6fcd..3de95ed7f 100644
--- a/javax/swing/text/FlowView.java
+++ b/javax/swing/text/FlowView.java
@@ -524,6 +524,7 @@ public abstract class FlowView extends BoxView
*/
public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory vf)
{
+ layoutPool.removeUpdate(changes, a, vf);
strategy.removeUpdate(this, changes, getInsideAllocation(a));
layoutDirty = true;
}
@@ -539,6 +540,7 @@ public abstract class FlowView extends BoxView
*/
public void changedUpdate(DocumentEvent changes, Shape a, ViewFactory vf)
{
+ layoutPool.changedUpdate(changes, a, vf);
strategy.changedUpdate(this, changes, getInsideAllocation(a));
layoutDirty = true;
}
@@ -597,12 +599,14 @@ public abstract class FlowView extends BoxView
protected SizeRequirements calculateMinorAxisRequirements(int axis,
SizeRequirements r)
{
- // We need to call super here so that the alignment is properly
- // calculated.
- SizeRequirements res = super.calculateMinorAxisRequirements(axis, r);
+ SizeRequirements res = r;
+ if (res == null)
+ res = new SizeRequirements();
res.minimum = (int) layoutPool.getMinimumSpan(axis);
- res.preferred = (int) layoutPool.getPreferredSpan(axis);
- res.maximum = (int) layoutPool.getMaximumSpan(axis);
+ res.preferred = Math.max(res.minimum,
+ (int) layoutPool.getMinimumSpan(axis));
+ res.maximum = Integer.MAX_VALUE;
+ res.alignment = 0.5F;
return res;
}
}
diff --git a/javax/swing/text/GapContent.java b/javax/swing/text/GapContent.java
index eacd29c7b..7b1502777 100644
--- a/javax/swing/text/GapContent.java
+++ b/javax/swing/text/GapContent.java
@@ -195,10 +195,52 @@ public class GapContent
}
}
+ /**
+ * Stores a reference to a mark that can be resetted to the original value
+ * after a mark has been moved. This is used for undoing actions.
+ */
+ private class UndoPosRef
+ {
+ /**
+ * The mark that might need to be reset.
+ */
+ private Mark mark;
+
+ /**
+ * The original offset to reset the mark to.
+ */
+ private int undoOffset;
+
+ /**
+ * Creates a new UndoPosRef.
+ *
+ * @param m the mark
+ */
+ UndoPosRef(Mark m)
+ {
+ mark = m;
+ undoOffset = mark.getOffset();
+ }
+
+ /**
+ * Resets the position of the mark to the value that it had when
+ * creating this UndoPosRef.
+ */
+ void reset()
+ {
+ if (undoOffset <= gapStart)
+ mark.mark = undoOffset;
+ else
+ mark.mark = (gapEnd - gapStart) + undoOffset;
+ }
+ }
+
private class InsertUndo extends AbstractUndoableEdit
{
public int where, length;
String text;
+ private Vector positions;
+
public InsertUndo(int start, int len)
{
where = start;
@@ -209,27 +251,33 @@ public class GapContent
{
super.undo();
try
- {
- text = getString(where, length);
- remove(where, length);
- }
+ {
+ positions = getPositionsInRange(null, where, length);
+ text = getString(where, length);
+ remove(where, length);
+ }
catch (BadLocationException ble)
- {
- throw new CannotUndoException();
- }
+ {
+ throw new CannotUndoException();
+ }
}
public void redo () throws CannotUndoException
{
super.redo();
try
- {
- insertString(where, text);
- }
+ {
+ insertString(where, text);
+ if (positions != null)
+ {
+ updateUndoPositions(positions, where, length);
+ positions = null;
+ }
+ }
catch (BadLocationException ble)
- {
- throw new CannotRedoException();
- }
+ {
+ throw new CannotRedoException();
+ }
}
}
@@ -238,10 +286,17 @@ public class GapContent
{
public int where;
String text;
+
+ /**
+ * The positions in the removed range.
+ */
+ private Vector positions;
+
public UndoRemove(int start, String removedText)
{
where = start;
text = removedText;
+ positions = getPositionsInRange(null, start, removedText.length());
}
public void undo () throws CannotUndoException
@@ -250,6 +305,8 @@ public class GapContent
try
{
insertString(where, text);
+ if (positions != null)
+ updateUndoPositions(positions, where, text.length());
}
catch (BadLocationException ble)
{
@@ -261,13 +318,15 @@ public class GapContent
{
super.redo();
try
- {
- remove(where, text.length());
- }
+ {
+ text = getString(where, text.length());
+ positions = getPositionsInRange(null, where, text.length());
+ remove(where, text.length());
+ }
catch (BadLocationException ble)
- {
- throw new CannotRedoException();
- }
+ {
+ throw new CannotRedoException();
+ }
}
}
@@ -403,9 +462,10 @@ public class GapContent
throw new BadLocationException("The where argument cannot be greater"
+ " than the content length", where);
+ InsertUndo undo = new InsertUndo(where, strLen);
replace(where, 0, str.toCharArray(), strLen);
- return new InsertUndo(where, strLen);
+ return undo;
}
/**
@@ -429,9 +489,10 @@ public class GapContent
+ " than the content length", where + nitems);
String removedText = getString(where, nitems);
+ UndoRemove undoRemove = new UndoRemove(where, removedText);
replace(where, nitems, null, 0);
- return new UndoRemove(where, removedText);
+ return undoRemove;
}
/**
@@ -492,30 +553,46 @@ public class GapContent
if ((where + len) > length)
throw new BadLocationException("len plus where cannot be greater"
+ " than the content length", len + where);
+ if (len < 0)
+ throw new BadLocationException("negative length not allowed: ", len);
- // check if requested segment is contiguous
- if ((where < gapStart) && ((gapStart - where) < len))
- {
- // requested segment is not contiguous -> copy the pieces together
- char[] copy = new char[len];
- int lenFirst = gapStart - where; // the length of the first segment
- System.arraycopy(buffer, where, copy, 0, lenFirst);
- System.arraycopy(buffer, gapEnd, copy, lenFirst, len - lenFirst);
- txt.array = copy;
- txt.offset = 0;
- txt.count = len;
- }
- else
- {
- // requested segment is contiguous -> we can simply return the
- // actual content
- txt.array = buffer;
- if (where < gapStart)
+ // Optimized to copy only when really needed.
+ if (where + len <= gapStart)
+ {
+ // Simple case: completely before gap.
+ txt.array = buffer;
txt.offset = where;
- else
- txt.offset = where + (gapEnd - gapStart);
- txt.count = len;
- }
+ txt.count = len;
+ }
+ else if (where > gapStart)
+ {
+ // Completely after gap, adjust offset.
+ txt.array = buffer;
+ txt.offset = gapEnd + where - gapStart;
+ txt.count = len;
+ }
+ else
+ {
+ // Spans the gap.
+ int beforeGap = gapStart - where;
+ if (txt.isPartialReturn())
+ {
+ // Return the part before the gap when partial return is allowed.
+ txt.array = buffer;
+ txt.offset = where;
+ txt.count = beforeGap;
+ }
+ else
+ {
+ // Copy pieces together otherwise.
+ txt.array = new char[len];
+ txt.offset = 0;
+ System.arraycopy(buffer, where, txt.array, 0, beforeGap);
+ System.arraycopy(buffer, gapEnd, txt.array, beforeGap,
+ len - beforeGap);
+ txt.count = len;
+ }
+ }
}
/**
@@ -530,8 +607,10 @@ public class GapContent
*/
public Position createPosition(final int offset) throws BadLocationException
{
- if (offset < 0 || offset > length())
- throw new BadLocationException("Position offset out of bounds", offset);
+ // Implementation note: We used to perform explicit check on the offset
+ // here. However, this makes some Mauve and Intel/Harmony tests fail
+ // and luckily enough the GapContent can very well deal with offsets
+ // outside the buffer bounds. So I removed that check.
// We try to find a GapContentPosition at the specified offset and return
// that. Otherwise we must create a new one.
@@ -572,7 +651,7 @@ public class GapContent
int delta = newSize - gapEnd + gapStart;
// Update the marks after the gapEnd.
- adjustPositionsInRange(gapEnd, buffer.length, delta);
+ adjustPositionsInRange(gapEnd, -1, delta);
// Copy the data around.
char[] newBuf = (char[]) allocateArray(length() + newSize);
@@ -732,8 +811,6 @@ public class GapContent
Vector res = v;
if (res == null)
res = new Vector();
- else
- res.clear();
int endOffs = offset + length;
@@ -742,8 +819,8 @@ public class GapContent
{
GapContentPosition p = (GapContentPosition) i.next();
int offs = p.getOffset();
- if (offs >= offset && offs < endOffs)
- res.add(p);
+ if (offs >= offset && offs <= endOffs)
+ res.add(new UndoPosRef(p.mark));
}
return res;
@@ -787,7 +864,7 @@ public class GapContent
* the buffer array by <code>increment</code>
*
* @param startOffs the start offset of the range to search
- * @param endOffs the length of the range to search
+ * @param endOffs the length of the range to search, -1 means all to the end
* @param incr the increment
*/
private void adjustPositionsInRange(int startOffs, int endOffs, int incr)
@@ -803,9 +880,15 @@ public class GapContent
startIndex = - startIndex - 1;
m.mark = endOffs;
- int endIndex = search(marks, m);
- if (endIndex < 0) // Translate to insertion index - 1, if not found.
- endIndex = - endIndex - 2;
+ int endIndex;
+ if (endOffs == -1)
+ endIndex = marks.size() - 1;
+ else
+ {
+ endIndex = search(marks, m);
+ if (endIndex < 0) // Translate to insertion index - 1, if not found.
+ endIndex = - endIndex - 2;
+ }
// Actually adjust the marks.
for (int i = startIndex; i <= endIndex; i++) {
((Mark) marks.get(i)).mark += incr;
@@ -834,14 +917,26 @@ public class GapContent
}
/**
- * @specnote This method is not very well specified and the positions vector
- * is implementation specific. The undo positions are managed
- * differently in this implementation, this method is only here
- * for binary compatibility.
+ * Resets the positions in the specified range to their original offset
+ * after a undo operation is performed. For example, after removing some
+ * content, the positions in the removed range will all be set to one
+ * offset. This method restores the positions to their original offsets
+ * after an undo.
+ *
+ * @param positions the positions to update
+ * @param offset
+ * @param length
*/
protected void updateUndoPositions(Vector positions, int offset, int length)
{
- // We do nothing here.
+ for (Iterator i = positions.iterator(); i.hasNext();)
+ {
+ UndoPosRef undoPosRef = (UndoPosRef) i.next();
+ undoPosRef.reset();
+ }
+
+ // Resort marks.
+ Collections.sort(marks);
}
/**
diff --git a/javax/swing/text/GlyphView.java b/javax/swing/text/GlyphView.java
index d505274c9..65025dd08 100644
--- a/javax/swing/text/GlyphView.java
+++ b/javax/swing/text/GlyphView.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package javax.swing.text;
import java.awt.Color;
+import java.awt.Container;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
@@ -354,11 +355,14 @@ public class GlyphView extends View implements TabableView, Cloneable
Font font = view.getFont();
FontMetrics fm = view.getContainer().getFontMetrics(font);
Segment txt = view.getText(el.getStartOffset(), pos);
- int width = fm.charsWidth(txt.array, txt.offset, txt.count);
+ Rectangle bounds = a instanceof Rectangle ? (Rectangle) a
+ : a.getBounds();
+ TabExpander expander = view.getTabExpander();
+ int width = Utilities.getTabbedTextWidth(txt, fm, bounds.x, expander,
+ view.getStartOffset());
int height = fm.getHeight();
- Rectangle bounds = a.getBounds();
Rectangle result = new Rectangle(bounds.x + width, bounds.y,
- bounds.x + width, height);
+ 0, height);
return result;
}
@@ -536,9 +540,24 @@ public class GlyphView extends View implements TabableView, Cloneable
*/
public void paint(Graphics g, Shape a)
{
- Element el = getElement();
checkPainter();
- getGlyphPainter().paint(this, g, a, getStartOffset(), getEndOffset());
+ int p0 = getStartOffset();
+ int p1 = getEndOffset();
+
+ Container c = getContainer();
+ // Paint layered highlights if there are any.
+ if (c instanceof JTextComponent)
+ {
+ JTextComponent tc = (JTextComponent) c;
+ Highlighter h = tc.getHighlighter();
+ if (h instanceof LayeredHighlighter)
+ {
+ LayeredHighlighter lh = (LayeredHighlighter) h;
+ lh.paintLayeredHighlights(g, p0, p1, a, tc, this);
+ }
+ }
+
+ getGlyphPainter().paint(this, g, a, p0, p1);
}
diff --git a/javax/swing/text/IconView.java b/javax/swing/text/IconView.java
index 699cda90e..7bb7635b4 100644
--- a/javax/swing/text/IconView.java
+++ b/javax/swing/text/IconView.java
@@ -44,7 +44,6 @@ import java.awt.Shape;
import javax.swing.Icon;
import javax.swing.JTextPane;
-import javax.swing.SwingConstants;
/**
* A View that can render an icon. This view is created by the
@@ -156,4 +155,21 @@ public class IconView
return el.getStartOffset();
}
+ /**
+ * Returns the alignment for this view. This will be 1.0 for the Y_AXIS,
+ * and the super behaviour for the X_AXIS.
+ *
+ * @param axis the axis for which to calculate the alignment
+ *
+ * @return the alignment
+ */
+ public float getAlignment(int axis)
+ {
+ float align;
+ if (axis == Y_AXIS)
+ align = 1.0F;
+ else
+ align = super.getAlignment(axis);
+ return align;
+ }
}
diff --git a/javax/swing/text/JTextComponent.java b/javax/swing/text/JTextComponent.java
index 6da84bfe7..68ba1f428 100644
--- a/javax/swing/text/JTextComponent.java
+++ b/javax/swing/text/JTextComponent.java
@@ -38,8 +38,6 @@ exception statement from your version. */
package javax.swing.text;
-import gnu.classpath.NotImplementedException;
-
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Container;
@@ -47,6 +45,7 @@ import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
+import java.awt.Shape;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
@@ -59,6 +58,7 @@ import java.awt.event.MouseEvent;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
+import java.text.BreakIterator;
import java.util.Enumeration;
import java.util.Hashtable;
@@ -67,6 +67,7 @@ import javax.accessibility.AccessibleAction;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleEditableText;
import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;
import javax.accessibility.AccessibleText;
import javax.swing.Action;
@@ -105,12 +106,7 @@ public abstract class JTextComponent extends JComponent
/**
* The caret's offset.
*/
- int dot = 0;
-
- /**
- * The current JTextComponent.
- */
- JTextComponent textComp = JTextComponent.this;
+ private int caretDot;
/**
* Construct an AccessibleJTextComponent.
@@ -118,7 +114,8 @@ public abstract class JTextComponent extends JComponent
public AccessibleJTextComponent()
{
super();
- textComp.addCaretListener(this);
+ JTextComponent.this.addCaretListener(this);
+ caretDot = getCaretPosition();
}
/**
@@ -129,8 +126,7 @@ public abstract class JTextComponent extends JComponent
*/
public int getCaretPosition()
{
- dot = textComp.getCaretPosition();
- return dot;
+ return JTextComponent.this.getCaretPosition();
}
/**
@@ -141,7 +137,7 @@ public abstract class JTextComponent extends JComponent
*/
public String getSelectedText()
{
- return textComp.getSelectedText();
+ return JTextComponent.this.getSelectedText();
}
/**
@@ -156,9 +152,10 @@ public abstract class JTextComponent extends JComponent
*/
public int getSelectionStart()
{
- if (getSelectedText() == null || (textComp.getText().equals("")))
+ if (getSelectedText() == null
+ || (JTextComponent.this.getText().equals("")))
return 0;
- return textComp.getSelectionStart();
+ return JTextComponent.this.getSelectionStart();
}
/**
@@ -173,9 +170,7 @@ public abstract class JTextComponent extends JComponent
*/
public int getSelectionEnd()
{
- if (getSelectedText() == null || (textComp.getText().equals("")))
- return 0;
- return textComp.getSelectionEnd();
+ return JTextComponent.this.getSelectionEnd();
}
/**
@@ -185,10 +180,20 @@ public abstract class JTextComponent extends JComponent
* @param e - the caret update event
*/
public void caretUpdate(CaretEvent e)
- throws NotImplementedException
{
- // TODO: fire appropriate event.
- dot = e.getDot();
+ int dot = e.getDot();
+ int mark = e.getMark();
+ if (caretDot != dot)
+ {
+ firePropertyChange(ACCESSIBLE_CARET_PROPERTY, new Integer(caretDot),
+ new Integer(dot));
+ caretDot = dot;
+ }
+ if (mark != dot)
+ {
+ firePropertyChange(ACCESSIBLE_SELECTION_PROPERTY, null,
+ getSelectedText());
+ }
}
/**
@@ -197,10 +202,10 @@ public abstract class JTextComponent extends JComponent
* @return the accessible state set of this component
*/
public AccessibleStateSet getAccessibleStateSet()
- throws NotImplementedException
{
AccessibleStateSet state = super.getAccessibleStateSet();
- // TODO: Figure out what state must be added here to the super's state.
+ if (isEditable())
+ state.add(AccessibleState.EDITABLE);
return state;
}
@@ -248,9 +253,9 @@ public abstract class JTextComponent extends JComponent
* @param e - the insertion event
*/
public void insertUpdate(DocumentEvent e)
- throws NotImplementedException
{
- // TODO
+ firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null,
+ new Integer(e.getOffset()));
}
/**
@@ -261,9 +266,9 @@ public abstract class JTextComponent extends JComponent
* @param e - the removal event
*/
public void removeUpdate(DocumentEvent e)
- throws NotImplementedException
{
- // TODO
+ firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null,
+ new Integer(e.getOffset()));
}
/**
@@ -274,9 +279,9 @@ public abstract class JTextComponent extends JComponent
* @param e - text change event
*/
public void changedUpdate(DocumentEvent e)
- throws NotImplementedException
{
- // TODO
+ firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null,
+ new Integer(e.getOffset()));
}
/**
@@ -289,9 +294,8 @@ public abstract class JTextComponent extends JComponent
* @return a character index, or -1
*/
public int getIndexAtPoint(Point p)
- throws NotImplementedException
{
- return 0; // TODO
+ return viewToModel(p);
}
/**
@@ -305,9 +309,51 @@ public abstract class JTextComponent extends JComponent
* @return a character's bounding box, or null
*/
public Rectangle getCharacterBounds(int index)
- throws NotImplementedException
{
- return null; // TODO
+ // This is basically the same as BasicTextUI.modelToView().
+
+ Rectangle bounds = null;
+ if (index >= 0 && index < doc.getLength() - 1)
+ {
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).readLock();
+ try
+ {
+ TextUI ui = getUI();
+ if (ui != null)
+ {
+ // Get editor rectangle.
+ Rectangle rect = new Rectangle();
+ Insets insets = getInsets();
+ rect.x = insets.left;
+ rect.y = insets.top;
+ rect.width = getWidth() - insets.left - insets.right;
+ rect.height = getHeight() - insets.top - insets.bottom;
+ View rootView = ui.getRootView(JTextComponent.this);
+ if (rootView != null)
+ {
+ rootView.setSize(rect.width, rect.height);
+ Shape s = rootView.modelToView(index,
+ Position.Bias.Forward,
+ index + 1,
+ Position.Bias.Backward,
+ rect);
+ if (s != null)
+ bounds = s.getBounds();
+ }
+ }
+ }
+ catch (BadLocationException ex)
+ {
+ // Ignore (return null).
+ }
+ finally
+ {
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).readUnlock();
+ }
+ }
+ return bounds;
}
/**
@@ -317,7 +363,7 @@ public abstract class JTextComponent extends JComponent
*/
public int getCharCount()
{
- return textComp.getText().length();
+ return JTextComponent.this.getText().length();
}
/**
@@ -329,9 +375,26 @@ public abstract class JTextComponent extends JComponent
* @return the character's attributes
*/
public AttributeSet getCharacterAttribute(int index)
- throws NotImplementedException
{
- return null; // TODO
+ AttributeSet atts;
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).readLock();
+ try
+ {
+ Element el = doc.getDefaultRootElement();
+ while (! el.isLeaf())
+ {
+ int i = el.getElementIndex(index);
+ el = el.getElement(i);
+ }
+ atts = el.getAttributes();
+ }
+ finally
+ {
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).readUnlock();
+ }
+ return atts;
}
/**
@@ -344,9 +407,8 @@ public abstract class JTextComponent extends JComponent
* @return the part of text at that index, or null
*/
public String getAtIndex(int part, int index)
- throws NotImplementedException
{
- return null; // TODO
+ return getAtIndexImpl(part, index, 0);
}
/**
@@ -359,9 +421,8 @@ public abstract class JTextComponent extends JComponent
* @return the part of text after that index, or null
*/
public String getAfterIndex(int part, int index)
- throws NotImplementedException
{
- return null; // TODO
+ return getAtIndexImpl(part, index, 1);
}
/**
@@ -374,11 +435,84 @@ public abstract class JTextComponent extends JComponent
* @return the part of text before that index, or null
*/
public String getBeforeIndex(int part, int index)
- throws NotImplementedException
{
- return null; // TODO
+ return getAtIndexImpl(part, index, -1);
}
-
+
+ /**
+ * Implements getAtIndex(), getBeforeIndex() and getAfterIndex().
+ *
+ * @param part the part to return, either CHARACTER, WORD or SENTENCE
+ * @param index the index
+ * @param dir the direction, -1 for backwards, 0 for here, +1 for forwards
+ *
+ * @return the resulting string
+ */
+ private String getAtIndexImpl(int part, int index, int dir)
+ {
+ String ret = null;
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).readLock();
+ try
+ {
+ BreakIterator iter = null;
+ switch (part)
+ {
+ case CHARACTER:
+ iter = BreakIterator.getCharacterInstance(getLocale());
+ break;
+ case WORD:
+ iter = BreakIterator.getWordInstance(getLocale());
+ break;
+ case SENTENCE:
+ iter = BreakIterator.getSentenceInstance(getLocale());
+ break;
+ default:
+ break;
+ }
+ String text = doc.getText(0, doc.getLength() - 1);
+ iter.setText(text);
+ int start = index;
+ int end = index;
+ switch (dir)
+ {
+ case 0:
+ if (iter.isBoundary(index))
+ {
+ start = index;
+ end = iter.following(index);
+ }
+ else
+ {
+ start = iter.preceding(index);
+ end = iter.next();
+ }
+ break;
+ case 1:
+ start = iter.following(index);
+ end = iter.next();
+ break;
+ case -1:
+ end = iter.preceding(index);
+ start = iter.previous();
+ break;
+ default:
+ assert false;
+ }
+ ret = text.substring(start, end);
+ }
+ catch (BadLocationException ex)
+ {
+ // Ignore (return null).
+ }
+ finally
+ {
+ if (doc instanceof AbstractDocument)
+ ((AbstractDocument) doc).readUnlock();
+ }
+ return ret;
+ }
+
/**
* Returns the number of actions for this object. The zero-th
* object represents the default action.
@@ -386,9 +520,8 @@ public abstract class JTextComponent extends JComponent
* @return the number of actions (0-based).
*/
public int getAccessibleActionCount()
- throws NotImplementedException
{
- return 0; // TODO
+ return getActions().length;
}
/**
@@ -400,10 +533,12 @@ public abstract class JTextComponent extends JComponent
* @return description of the i-th action
*/
public String getAccessibleActionDescription(int i)
- throws NotImplementedException
{
- // TODO: Not implemented fully
- return super.getAccessibleDescription();
+ String desc = null;
+ Action[] actions = getActions();
+ if (i >= 0 && i < actions.length)
+ desc = (String) actions[i].getValue(Action.NAME);
+ return desc;
}
/**
@@ -415,9 +550,17 @@ public abstract class JTextComponent extends JComponent
* @return true if the action was performed successfully
*/
public boolean doAccessibleAction(int i)
- throws NotImplementedException
{
- return false; // TODO
+ boolean ret = false;
+ Action[] actions = getActions();
+ if (i >= 0 && i < actions.length)
+ {
+ ActionEvent ev = new ActionEvent(JTextComponent.this,
+ ActionEvent.ACTION_PERFORMED, null);
+ actions[i].actionPerformed(ev);
+ ret = true;
+ }
+ return ret;
}
/**
@@ -426,9 +569,8 @@ public abstract class JTextComponent extends JComponent
* @param s - the new text contents.
*/
public void setTextContents(String s)
- throws NotImplementedException
{
- // TODO
+ setText(s);
}
/**
@@ -438,9 +580,16 @@ public abstract class JTextComponent extends JComponent
* @param s - the new text
*/
public void insertTextAtIndex(int index, String s)
- throws NotImplementedException
{
- replaceText(index, index, s);
+ try
+ {
+ doc.insertString(index, s, null);
+ }
+ catch (BadLocationException ex)
+ {
+ // What should we do with this?
+ ex.printStackTrace();
+ }
}
/**
@@ -453,7 +602,7 @@ public abstract class JTextComponent extends JComponent
{
try
{
- return textComp.getText(start, end - start);
+ return JTextComponent.this.getText(start, end - start);
}
catch (BadLocationException ble)
{
@@ -481,8 +630,8 @@ public abstract class JTextComponent extends JComponent
*/
public void cut(int start, int end)
{
- textComp.select(start, end);
- textComp.cut();
+ JTextComponent.this.select(start, end);
+ JTextComponent.this.cut();
}
/**
@@ -492,8 +641,8 @@ public abstract class JTextComponent extends JComponent
*/
public void paste(int start)
{
- textComp.setCaretPosition(start);
- textComp.paste();
+ JTextComponent.this.setCaretPosition(start);
+ JTextComponent.this.paste();
}
/**
@@ -506,8 +655,8 @@ public abstract class JTextComponent extends JComponent
*/
public void replaceText(int start, int end, String s)
{
- textComp.select(start, end);
- textComp.replaceSelection(s);
+ JTextComponent.this.select(start, end);
+ JTextComponent.this.replaceSelection(s);
}
/**
@@ -518,7 +667,7 @@ public abstract class JTextComponent extends JComponent
*/
public void selectText(int start, int end)
{
- textComp.select(start, end);
+ JTextComponent.this.select(start, end);
}
/**
@@ -529,9 +678,12 @@ public abstract class JTextComponent extends JComponent
* @param s - the new attribute set for the text in the range
*/
public void setAttributes(int start, int end, AttributeSet s)
- throws NotImplementedException
{
- // TODO
+ if (doc instanceof StyledDocument)
+ {
+ StyledDocument sdoc = (StyledDocument) doc;
+ sdoc.setCharacterAttributes(start, end - start, s, true);
+ }
}
}
diff --git a/javax/swing/text/LabelView.java b/javax/swing/text/LabelView.java
index 03279c4b2..a00a49c24 100644
--- a/javax/swing/text/LabelView.java
+++ b/javax/swing/text/LabelView.java
@@ -39,9 +39,11 @@ exception statement from your version. */
package javax.swing.text;
import java.awt.Color;
+import java.awt.Container;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Shape;
+import java.awt.Toolkit;
import javax.swing.event.DocumentEvent;
@@ -90,6 +92,11 @@ public class LabelView extends GlyphView
boolean superscript;
/**
+ * Indicates if the attributes must be refetched.
+ */
+ private boolean valid;
+
+ /**
* Creates a new <code>GlyphView</code> for the given <code>Element</code>.
*
* @param element the element that is rendered by this GlyphView
@@ -97,7 +104,7 @@ public class LabelView extends GlyphView
public LabelView(Element element)
{
super(element);
- setPropertiesFromAttributes();
+ valid = false;
}
/**
@@ -115,10 +122,10 @@ public class LabelView extends GlyphView
// when background == null anyway.
background = (Color) atts.getAttribute(StyleConstants.Background);
foreground = StyleConstants.getForeground(atts);
- strikeThrough = StyleConstants.isStrikeThrough(atts);
- subscript = StyleConstants.isSubscript(atts);
- superscript = StyleConstants.isSuperscript(atts);
- underline = StyleConstants.isUnderline(atts);
+ setStrikeThrough(StyleConstants.isStrikeThrough(atts));
+ setSubscript(StyleConstants.isSubscript(atts));
+ setSuperscript(StyleConstants.isSuperscript(atts));
+ setUnderline(StyleConstants.isUnderline(atts));
// Determine the font.
String family = StyleConstants.getFontFamily(atts);
@@ -129,6 +136,7 @@ public class LabelView extends GlyphView
if (StyleConstants.isItalic(atts))
style |= Font.ITALIC;
font = new Font(family, style, size);
+ valid = true;
}
/**
@@ -142,7 +150,8 @@ public class LabelView extends GlyphView
*/
public void changedUpdate(DocumentEvent e, Shape a, ViewFactory vf)
{
- setPropertiesFromAttributes();
+ valid = false;
+ super.changedUpdate(e, a, vf);
}
/**
@@ -152,6 +161,8 @@ public class LabelView extends GlyphView
*/
public Color getBackground()
{
+ if (! valid)
+ setPropertiesFromAttributes();
return background;
}
@@ -175,6 +186,8 @@ public class LabelView extends GlyphView
*/
public Color getForeground()
{
+ if (! valid)
+ setPropertiesFromAttributes();
return foreground;
}
@@ -185,6 +198,8 @@ public class LabelView extends GlyphView
*/
public Font getFont()
{
+ if (! valid)
+ setPropertiesFromAttributes();
return font;
}
@@ -197,7 +212,16 @@ public class LabelView extends GlyphView
*/
protected FontMetrics getFontMetrics()
{
- return getContainer().getGraphics().getFontMetrics(font);
+ if (! valid)
+ setPropertiesFromAttributes();
+
+ Container c = getContainer();
+ FontMetrics fm;
+ if (c != null)
+ fm = c.getFontMetrics(font);
+ else
+ fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
+ return fm;
}
/**
@@ -209,6 +233,8 @@ public class LabelView extends GlyphView
*/
public boolean isUnderline()
{
+ if (! valid)
+ setPropertiesFromAttributes();
return underline;
}
@@ -255,6 +281,8 @@ public class LabelView extends GlyphView
*/
public boolean isSuperscript()
{
+ if (! valid)
+ setPropertiesFromAttributes();
return superscript;
}
@@ -278,6 +306,8 @@ public class LabelView extends GlyphView
*/
public boolean isStrikeThrough()
{
+ if (! valid)
+ setPropertiesFromAttributes();
return strikeThrough;
}
diff --git a/javax/swing/text/ParagraphView.java b/javax/swing/text/ParagraphView.java
index 15bed7818..8a35ff62f 100644
--- a/javax/swing/text/ParagraphView.java
+++ b/javax/swing/text/ParagraphView.java
@@ -74,6 +74,39 @@ public class ParagraphView extends FlowView implements TabExpander
return align;
}
+ /**
+ * Allows rows to span the whole parent view.
+ */
+ public float getMaximumSpan(int axis)
+ {
+ float max;
+ if (axis == X_AXIS)
+ max = Float.MAX_VALUE;
+ else
+ max = super.getMaximumSpan(axis);
+ return max;
+ }
+
+ /**
+ * Overridden because child views are not necessarily laid out in model
+ * order.
+ */
+ protected int getViewIndexAtPosition(int pos)
+ {
+ int index = -1;
+ if (pos >= getStartOffset() && pos < getEndOffset())
+ {
+ int nviews = getViewCount();
+ for (int i = 0; i < nviews && index == -1; i++)
+ {
+ View child = getView(i);
+ if (pos >= child.getStartOffset() && pos < child.getEndOffset())
+ index = i;
+ }
+ }
+ return index;
+ }
+
protected void loadChildren(ViewFactory vf)
{
// Do nothing here. The children are added while layouting.
@@ -140,7 +173,7 @@ public class ParagraphView extends FlowView implements TabExpander
{
float align;
if (axis == X_AXIS)
- align = super.getAlignment(axis);
+ align = 0.5F;
else if (getViewCount() > 0)
{
float prefHeight = getPreferredSpan(Y_AXIS);
@@ -148,7 +181,7 @@ public class ParagraphView extends FlowView implements TabExpander
align = (firstRowHeight / 2.F) / prefHeight;
}
else
- align = 0.0F;
+ align = 0.5F;
return align;
}
@@ -159,11 +192,14 @@ public class ParagraphView extends FlowView implements TabExpander
*
* @param ev the document event
* @param a the allocation of this view
- * @param fv the view factory to use for creating new child views
+ * @param vf the view factory to use for creating new child views
*/
- public void changedUpdate(DocumentEvent ev, Shape a, ViewFactory fv)
+ public void changedUpdate(DocumentEvent ev, Shape a, ViewFactory vf)
{
setPropertiesFromAttributes();
+ layoutChanged(X_AXIS);
+ layoutChanged(Y_AXIS);
+ super.changedUpdate(ev, a, vf);
}
/**
diff --git a/javax/swing/text/PlainView.java b/javax/swing/text/PlainView.java
index 48fe37ce8..e048d5f71 100644
--- a/javax/swing/text/PlainView.java
+++ b/javax/swing/text/PlainView.java
@@ -87,6 +87,16 @@ public class PlainView extends View implements TabExpander
*/
private transient Segment lineBuffer;
+ /**
+ * The base offset for tab calculations.
+ */
+ private int tabBase;
+
+ /**
+ * The tab size.
+ */
+ private int tabSize;
+
public PlainView(Element elem)
{
super(elem);
@@ -104,6 +114,7 @@ public class PlainView extends View implements TabExpander
{
this.font = font;
metrics = component.getFontMetrics(font);
+ tabSize = getTabSize() * metrics.charWidth('m');
}
}
@@ -115,7 +126,7 @@ public class PlainView extends View implements TabExpander
// Ensure metrics are up-to-date.
updateMetrics();
- Rectangle rect = a.getBounds();
+ Rectangle rect = a instanceof Rectangle ? (Rectangle) a : a.getBounds();
int fontHeight = metrics.getHeight();
return new Rectangle(rect.x, rect.y + (line * fontHeight),
rect.width, fontHeight);
@@ -132,13 +143,14 @@ public class PlainView extends View implements TabExpander
// Get rectangle of the line containing position.
int lineIndex = getElement().getElementIndex(position);
Rectangle rect = lineToRect(a, lineIndex);
+ tabBase = rect.x;
// Get the rectangle for position.
Element line = getElement().getElement(lineIndex);
int lineStart = line.getStartOffset();
Segment segment = getLineBuffer();
document.getText(lineStart, position - lineStart, segment);
- int xoffset = Utilities.getTabbedTextWidth(segment, metrics, rect.x,
+ int xoffset = Utilities.getTabbedTextWidth(segment, metrics, tabBase,
this, lineStart);
// Calc the real rectangle.
@@ -262,17 +274,47 @@ public class PlainView extends View implements TabExpander
selectionStart = textComponent.getSelectionStart();
selectionEnd = textComponent.getSelectionEnd();
- Rectangle rect = s.getBounds();
+ Rectangle rect = s instanceof Rectangle ? (Rectangle) s : s.getBounds();
+ tabBase = rect.x;
// FIXME: Text may be scrolled.
Document document = textComponent.getDocument();
- Element root = document.getDefaultRootElement();
- int y = rect.y + metrics.getAscent();
+ Element root = getElement();
int height = metrics.getHeight();
-
+
+ // For layered highlighters we need to paint the layered highlights
+ // before painting any text.
+ LayeredHighlighter hl = null;
+ Highlighter h = textComponent.getHighlighter();
+ if (h instanceof LayeredHighlighter)
+ hl = (LayeredHighlighter) h;
+
int count = root.getElementCount();
- for (int i = 0; i < count; i++)
+
+ // Determine first and last line inside the clip.
+ Rectangle clip = g.getClipBounds();
+ SwingUtilities.computeIntersection(rect.x, rect.y, rect.width, rect.height,
+ clip);
+ int line0 = (clip.y - rect.y) / height;
+ line0 = Math.max(0, Math.min(line0, count - 1));
+ int line1 = (clip.y + clip.height - rect.y) / height;
+ line1 = Math.max(0, Math.min(line1, count - 1));
+ int y = rect.y + metrics.getAscent() + height * line0;
+ for (int i = line0; i <= line1; i++)
{
+ if (hl != null)
+ {
+ Element lineEl = root.getElement(i);
+ // Exclude the trailing newline from beeing highlighted.
+ if (i == count)
+ hl.paintLayeredHighlights(g, lineEl.getStartOffset(),
+ lineEl.getEndOffset(), s, textComponent,
+ this);
+ else
+ hl.paintLayeredHighlights(g, lineEl.getStartOffset(),
+ lineEl.getEndOffset() - 1, s,
+ textComponent, this);
+ }
drawLine(i, g, rect.x, y);
y += height;
}
@@ -303,8 +345,13 @@ public class PlainView extends View implements TabExpander
*/
public float nextTabStop(float x, int tabStop)
{
- float tabSizePixels = getTabSize() * metrics.charWidth('m');
- return (float) (Math.floor(x / tabSizePixels) + 1) * tabSizePixels;
+ float next = x;
+ if (tabSize != 0)
+ {
+ int numTabs = (((int) x) - tabBase) / tabSize;
+ next = tabBase + (numTabs + 1) * tabSize;
+ }
+ return next;
}
/**
@@ -390,41 +437,58 @@ public class PlainView extends View implements TabExpander
*/
public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
{
- Rectangle rec = a.getBounds();
- Document doc = getDocument();
- Element root = doc.getDefaultRootElement();
-
- // PlainView doesn't support line-wrapping so we can find out which
- // Element was clicked on just by the y-position.
- // Since the coordinates may be outside of the coordinate space
- // of the allocation area (e.g. user dragged mouse outside
- // the component) we have to limit the values.
- // This has the nice effect that the user can drag the
- // mouse above or below the component and it will still
- // react to the x values (e.g. when selecting).
- int lineClicked
- = Math.min(Math.max((int) (y - rec.y) / metrics.getHeight(), 0),
- root.getElementCount() - 1);
-
- Element line = root.getElement(lineClicked);
-
- Segment s = getLineBuffer();
- int start = line.getStartOffset();
- // We don't want the \n at the end of the line.
- int end = line.getEndOffset() - 1;
- try
- {
- doc.getText(start, end - start, s);
- }
- catch (BadLocationException ble)
+ Rectangle rec = a instanceof Rectangle ? (Rectangle) a : a.getBounds();
+ tabBase = rec.x;
+
+ int pos;
+ if ((int) y < rec.y)
+ // Above our area vertically. Return start offset.
+ pos = getStartOffset();
+ else if ((int) y > rec.y + rec.height)
+ // Below our area vertically. Return end offset.
+ pos = getEndOffset() - 1;
+ else
{
- AssertionError ae = new AssertionError("Unexpected bad location");
- ae.initCause(ble);
- throw ae;
+ // Inside the allocation vertically. Determine line and X offset.
+ Document doc = getDocument();
+ Element root = doc.getDefaultRootElement();
+ int line = Math.abs(((int) y - rec.y) / metrics.getHeight());
+ if (line >= root.getElementCount())
+ pos = getEndOffset() - 1;
+ else
+ {
+ Element lineEl = root.getElement(line);
+ if (x < rec.x)
+ // To the left of the allocation area.
+ pos = lineEl.getStartOffset();
+ else if (x > rec.x + rec.width)
+ // To the right of the allocation area.
+ pos = lineEl.getEndOffset() - 1;
+ else
+ {
+ try
+ {
+ int p0 = lineEl.getStartOffset();
+ int p1 = lineEl.getEndOffset();
+ Segment s = new Segment();
+ doc.getText(p0, p1 - p0, s);
+ tabBase = rec.x;
+ pos = p0 + Utilities.getTabbedTextOffset(s, metrics,
+ tabBase, (int) x,
+ this, p0);
+ }
+ catch (BadLocationException ex)
+ {
+ // Should not happen.
+ pos = -1;
+ }
+ }
+
+ }
}
-
- int pos = Utilities.getTabbedTextOffset(s, metrics, rec.x, (int)x, this, start);
- return Math.max (0, pos);
+ // Bias is always forward.
+ b[0] = Position.Bias.Forward;
+ return pos;
}
/**
@@ -654,7 +718,7 @@ public class PlainView extends View implements TabExpander
throw err;
}
- return Utilities.getTabbedTextWidth(buffer, metrics, 0, this,
+ return Utilities.getTabbedTextWidth(buffer, metrics, tabBase, this,
lineEl.getStartOffset());
}
}
diff --git a/javax/swing/text/Segment.java b/javax/swing/text/Segment.java
index d2364e05a..63c5fa09d 100644
--- a/javax/swing/text/Segment.java
+++ b/javax/swing/text/Segment.java
@@ -165,8 +165,9 @@ public class Segment implements Cloneable, CharacterIterator
/**
* Sets the current index to point to the last character in the segment and
- * returns that character. If the segment contains zero characters, this
- * method returns {@link #DONE}.
+ * returns that character. If the segment contains zero characters, the
+ * current index is set to {@link #getEndIndex()} and this method returns
+ * {@link #DONE}.
*
* @return The last character in the segment, or {@link #DONE} if the
* segment contains zero characters.
@@ -174,7 +175,10 @@ public class Segment implements Cloneable, CharacterIterator
public char last()
{
if (count == 0)
- return DONE;
+ {
+ current = getEndIndex();
+ return DONE;
+ }
current = getEndIndex() - 1;
return array[current];
diff --git a/javax/swing/text/SimpleAttributeSet.java b/javax/swing/text/SimpleAttributeSet.java
index 8dbcb0c6a..cdd3a7ee7 100644
--- a/javax/swing/text/SimpleAttributeSet.java
+++ b/javax/swing/text/SimpleAttributeSet.java
@@ -51,8 +51,10 @@ public class SimpleAttributeSet
/** The serialization UID (compatible with JDK1.5). */
private static final long serialVersionUID = 8267656273837665219L;
- /** An empty attribute set. */
- public static final AttributeSet EMPTY = new SimpleAttributeSet();
+ /**
+ * An empty attribute set.
+ */
+ public static final AttributeSet EMPTY = new EmptyAttributeSet();
/** Storage for the attributes. */
Hashtable tab;
@@ -121,9 +123,17 @@ public class SimpleAttributeSet
*/
public Object clone()
{
- SimpleAttributeSet s = new SimpleAttributeSet();
- s.tab = (Hashtable) tab.clone();
- return s;
+ SimpleAttributeSet attr = null;
+ try
+ {
+ attr = (SimpleAttributeSet) super.clone();
+ attr.tab = (Hashtable) tab.clone();
+ }
+ catch (CloneNotSupportedException ex)
+ {
+ assert false;
+ }
+ return attr;
}
/**
diff --git a/javax/swing/text/StringContent.java b/javax/swing/text/StringContent.java
index 0a31505f3..8014dc3bc 100644
--- a/javax/swing/text/StringContent.java
+++ b/javax/swing/text/StringContent.java
@@ -178,11 +178,13 @@ public final class StringContent
}
/**
- * Creates a new instance containing the string "\n".
+ * Creates a new instance containing the string "\n". This is equivalent
+ * to calling {@link #StringContent(int)} with an <code>initialLength</code>
+ * of 10.
*/
public StringContent()
{
- this(1);
+ this(10);
}
/**
diff --git a/javax/swing/text/StyleConstants.java b/javax/swing/text/StyleConstants.java
index c7906b8ad..677c479e5 100644
--- a/javax/swing/text/StyleConstants.java
+++ b/javax/swing/text/StyleConstants.java
@@ -729,6 +729,7 @@ public class StyleConstants
*/
public static void setIcon(MutableAttributeSet a, Icon c)
{
+ a.addAttribute(AbstractDocument.ElementNameAttribute, IconElementName);
a.addAttribute(IconAttribute, c);
}
diff --git a/javax/swing/text/StyledEditorKit.java b/javax/swing/text/StyledEditorKit.java
index c4eef4463..568694387 100644
--- a/javax/swing/text/StyledEditorKit.java
+++ b/javax/swing/text/StyledEditorKit.java
@@ -142,7 +142,7 @@ public class StyledEditorKit extends DefaultEditorKit
Element el = doc.getCharacterElement(editor.getSelectionStart());
boolean isBold = StyleConstants.isBold(el.getAttributes());
SimpleAttributeSet atts = new SimpleAttributeSet();
- StyleConstants.setItalic(atts, ! isBold);
+ StyleConstants.setBold(atts, ! isBold);
setCharacterAttributes(editor, atts, false);
}
}
@@ -335,35 +335,21 @@ public class StyledEditorKit extends DefaultEditorKit
AttributeSet atts,
boolean replace)
{
- Document doc = editor.getDocument();
- if (doc instanceof StyledDocument)
- {
- StyledDocument styleDoc = (StyledDocument) editor.getDocument();
- EditorKit kit = editor.getEditorKit();
- if (!(kit instanceof StyledEditorKit))
- {
- StyledEditorKit styleKit = (StyledEditorKit) kit;
- int start = editor.getSelectionStart();
- int end = editor.getSelectionEnd();
- int dot = editor.getCaret().getDot();
- if (start == dot && end == dot)
- {
- // If there is no selection, then we only update the
- // input attributes.
- MutableAttributeSet inputAttributes =
- styleKit.getInputAttributes();
- inputAttributes.addAttributes(atts);
- }
- else
- styleDoc.setCharacterAttributes(start, end, atts, replace);
- }
- else
- throw new AssertionError("The EditorKit for StyledTextActions "
- + "is expected to be a StyledEditorKit");
- }
- else
- throw new AssertionError("The Document for StyledTextActions is "
- + "expected to be a StyledDocument.");
+ int p0 = editor.getSelectionStart();
+ int p1 = editor.getSelectionEnd();
+ if (p0 != p1)
+ {
+ StyledDocument doc = getStyledDocument(editor);
+ doc.setCharacterAttributes(p0, p1 - p0, atts, replace);
+ }
+ // Update input attributes.
+ StyledEditorKit kit = getStyledEditorKit(editor);
+ MutableAttributeSet inputAtts = kit.getInputAttributes();
+ if (replace)
+ {
+ inputAtts.removeAttributes(inputAtts);
+ }
+ inputAtts.addAttributes(atts);
}
/**
diff --git a/javax/swing/text/TabSet.java b/javax/swing/text/TabSet.java
index ecad9444e..0f2c8c7c1 100644
--- a/javax/swing/text/TabSet.java
+++ b/javax/swing/text/TabSet.java
@@ -1,5 +1,5 @@
/* TabSet.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,23 +39,54 @@ package javax.swing.text;
import java.io.Serializable;
+/**
+ * A set of tab stops. Instances of this class are immutable.
+ */
public class TabSet implements Serializable
{
/** The serialization UID (compatible with JDK1.5). */
private static final long serialVersionUID = 2367703481999080593L;
+ /** Storage for the tab stops. */
TabStop[] tabs;
+ /**
+ * Creates a new <code>TabSet</code> containing the specified tab stops.
+ *
+ * @param t the tab stops (<code>null</code> permitted).
+ */
public TabSet(TabStop[] t)
{
- tabs = t;
+ if (t != null)
+ tabs = (TabStop[]) t.clone();
+ else
+ tabs = new TabStop[0];
}
+ /**
+ * Returns the tab stop with the specified index.
+ *
+ * @param i the index.
+ *
+ * @return The tab stop.
+ *
+ * @throws IllegalArgumentException if <code>i</code> is not in the range
+ * <code>0</code> to <code>getTabCount() - 1</code>.
+ */
public TabStop getTab(int i)
{
+ if (i < 0 || i >= tabs.length)
+ throw new IllegalArgumentException("Index out of bounds.");
return tabs[i];
}
+ /**
+ * Returns the tab following the specified location.
+ *
+ * @param location the location.
+ *
+ * @return The tab following the specified location (or <code>null</code>).
+ */
public TabStop getTabAfter(float location)
{
int idx = getTabIndexAfter(location);
@@ -65,11 +96,23 @@ public class TabSet implements Serializable
return tabs[idx];
}
+ /**
+ * Returns the number of tab stops in this tab set.
+ *
+ * @return The number of tab stops in this tab set.
+ */
public int getTabCount()
{
return tabs.length;
}
+ /**
+ * Returns the index of the specified tab, or -1 if the tab is not found.
+ *
+ * @param tab the tab (<code>null</code> permitted).
+ *
+ * @return The index of the specified tab, or -1.
+ */
public int getTabIndex(TabStop tab)
{
for (int i = 0; i < tabs.length; ++i)
@@ -78,28 +121,88 @@ public class TabSet implements Serializable
return -1;
}
+ /**
+ * Returns the index of the tab at or after the specified location.
+ *
+ * @param location the tab location.
+ *
+ * @return The index of the tab stop, or -1.
+ */
public int getTabIndexAfter(float location)
{
- int idx = -1;
- for (int i = 0; i < tabs.length; ++i)
+ for (int i = 0; i < tabs.length; i++)
+ {
+ if (location <= tabs[i].getPosition())
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Tests this <code>TabSet</code> for equality with an arbitrary object.
+ *
+ * @param obj the object (<code>null</code> permitted).
+ *
+ * @return <code>true</code> if this <code>TabSet</code> is equal to
+ * <code>obj</code>, and <code>false</code> otherwise.
+ *
+ * @since 1.5
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == this)
+ return true;
+ if (!(obj instanceof TabSet))
+ return false;
+ TabSet that = (TabSet) obj;
+ int tabCount = getTabCount();
+ if (tabCount != that.getTabCount())
+ return false;
+ for (int i = 0; i < tabCount; i++)
+ {
+ if (!this.getTab(i).equals(that.getTab(i)))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns a hash code for this <code>TabSet</code>.
+ *
+ * @return A hash code.
+ *
+ * @since 1.5
+ */
+ public int hashCode()
+ {
+ // this hash code won't match Sun's, but that shouldn't matter...
+ int result = 193;
+ int tabs = getTabCount();
+ for (int i = 0; i < tabs; i++)
{
- if (location < tabs[i].getPosition())
- idx = i;
+ TabStop t = getTab(i);
+ if (t != null)
+ result = 37 * result + t.hashCode();
}
- return idx;
+ return result;
}
+ /**
+ * Returns a string representation of this <code>TabSet</code>.
+ *
+ * @return A string representation of this <code>TabSet</code>.
+ */
public String toString()
{
StringBuffer sb = new StringBuffer();
- sb.append("[");
+ sb.append("[ ");
for (int i = 0; i < tabs.length; ++i)
{
if (i != 0)
sb.append(" - ");
sb.append(tabs[i].toString());
}
- sb.append("]");
+ sb.append(" ]");
return sb.toString();
}
}
diff --git a/javax/swing/text/TabStop.java b/javax/swing/text/TabStop.java
index 56f862fda..f4c3f8514 100644
--- a/javax/swing/text/TabStop.java
+++ b/javax/swing/text/TabStop.java
@@ -1,5 +1,5 @@
-/* TabSet.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+/* TabStop.java --
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,6 +39,9 @@ package javax.swing.text;
import java.io.Serializable;
+/**
+ * Represents a tab position in some text.
+ */
public class TabStop implements Serializable
{
/** The serialization UID (compatible with JDK1.5). */
@@ -61,18 +64,42 @@ public class TabStop implements Serializable
int align;
int leader;
+ /**
+ * Creates a new <code>TabStop</code> for the specified tab position.
+ *
+ * @param pos the tab position.
+ */
public TabStop(float pos)
{
this(pos, ALIGN_LEFT, LEAD_NONE);
}
+ /**
+ * Creates a new <code>TabStop</code> with the specified attributes.
+ *
+ * @param pos the tab position.
+ * @param align the alignment (one of {@link #ALIGN_LEFT},
+ * {@link #ALIGN_CENTER}, {@link #ALIGN_RIGHT}, {@link #ALIGN_DECIMAL}
+ * or {@link #ALIGN_BAR}).
+ * @param leader the leader (one of {@link #LEAD_NONE}, {@link #LEAD_DOTS},
+ * {@link #LEAD_EQUALS}, {@link #LEAD_HYPHENS}, {@link #LEAD_THICKLINE}
+ * or {@link #LEAD_UNDERLINE}).
+ */
public TabStop(float pos, int align, int leader)
{
this.pos = pos;
this.align = align;
this.leader = leader;
}
-
+
+ /**
+ * Tests this <code>TabStop</code> for equality with an arbitrary object.
+ *
+ * @param other the other object (<code>null</code> permitted).
+ *
+ * @return <code>true</code> if this <code>TabStop</code> is equal to
+ * the specified object, and <code>false</code> otherwise.
+ */
public boolean equals(Object other)
{
return (other != null)
@@ -82,34 +109,60 @@ public class TabStop implements Serializable
&& (((TabStop)other).getAlignment() == this.getAlignment());
}
+ /**
+ * Returns the tab alignment. This should be one of {@link #ALIGN_LEFT},
+ * {@link #ALIGN_CENTER}, {@link #ALIGN_RIGHT}, {@link #ALIGN_DECIMAL} or
+ * {@link #ALIGN_BAR}.
+ *
+ * @return The tab alignment.
+ */
public int getAlignment()
{
return align;
}
+ /**
+ * Returns the leader type. This should be one of {@link #LEAD_NONE},
+ * {@link #LEAD_DOTS}, {@link #LEAD_EQUALS}, {@link #LEAD_HYPHENS},
+ * {@link #LEAD_THICKLINE} or {@link #LEAD_UNDERLINE}.
+ *
+ * @return The leader type.
+ */
public int getLeader()
{
return leader;
}
+ /**
+ * Returns the tab position.
+ *
+ * @return The tab position.
+ */
public float getPosition()
{
return pos;
}
+ /**
+ * Returns a hash code for this <code>TabStop</code>.
+ *
+ * @return A hash code.
+ */
public int hashCode()
{
return (int) pos + (int) leader + (int) align;
}
+ /**
+ * Returns a string describing this <code>TabStop</code>.
+ *
+ * @return A string describing this <code>TabStop</code>.
+ */
public String toString()
{
String prefix = "";
switch (align)
{
- case ALIGN_LEFT:
- prefix = "left ";
- break;
case ALIGN_RIGHT:
prefix = "right ";
break;
@@ -130,7 +183,8 @@ public class TabStop implements Serializable
break;
}
- return (prefix + "tab @" + pos + ((leader == LEAD_NONE) ? "" : "(w/leaders)"));
+ return prefix + "tab @" + pos
+ + ((leader == LEAD_NONE) ? "" : " (w/leaders)");
}
}
diff --git a/javax/swing/text/TextAction.java b/javax/swing/text/TextAction.java
index 144166e9c..e18670610 100644
--- a/javax/swing/text/TextAction.java
+++ b/javax/swing/text/TextAction.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package javax.swing.text;
+import java.awt.Component;
+import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
@@ -45,7 +47,6 @@ import java.util.HashSet;
import javax.swing.AbstractAction;
import javax.swing.Action;
-import javax.swing.SwingConstants;
/**
* TextAction
@@ -108,7 +109,13 @@ public abstract class TextAction extends AbstractAction
*/
protected final JTextComponent getFocusedComponent()
{
- return null; // TODO
+ KeyboardFocusManager kfm =
+ KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ Component focused = kfm.getPermanentFocusOwner();
+ JTextComponent textComp = null;
+ if (focused instanceof JTextComponent)
+ textComp = (JTextComponent) focused;
+ return textComp;
}
/** Abstract helper class which implements everything needed for an
diff --git a/javax/swing/text/Utilities.java b/javax/swing/text/Utilities.java
index 36361f497..f0d3019ff 100644
--- a/javax/swing/text/Utilities.java
+++ b/javax/swing/text/Utilities.java
@@ -43,7 +43,6 @@ import java.awt.Graphics;
import java.awt.Point;
import java.text.BreakIterator;
-import javax.swing.SwingConstants;
import javax.swing.text.Position.Bias;
/**
@@ -109,7 +108,7 @@ public class Utilities
for (int offset = s.offset; offset < end; ++offset)
{
char c = buffer[offset];
- if (c == '\t' || c == '\n')
+ if (c == '\t')
{
if (len > 0) {
g.drawChars(buffer, pos, len, pixelX, pixelY + ascent);
@@ -131,11 +130,6 @@ public class Utilities
else
pixelX += metrics.charWidth(' ');
break;
- case '\n':
- // In case we have a newline, we must jump to the next line.
- pixelY += metrics.getHeight();
- pixelX = x;
- break;
default:
++len;
pixelWidth += metrics.charWidth(buffer[offset]);
@@ -712,12 +706,12 @@ public class Utilities
offset,
Bias.Forward,
direction,
- null)
+ new Position.Bias[1])
: t.getUI().getNextVisualPositionFrom(t,
offset,
Bias.Forward,
direction,
- null);
+ new Position.Bias[1]);
}
catch (BadLocationException ble)
{
diff --git a/javax/swing/text/View.java b/javax/swing/text/View.java
index d8ad5f585..068f969d2 100644
--- a/javax/swing/text/View.java
+++ b/javax/swing/text/View.java
@@ -401,7 +401,10 @@ public abstract class View implements SwingConstants
Element el = getElement();
DocumentEvent.ElementChange ec = ev.getChange(el);
if (ec != null)
- updateChildren(ec, ev, vf);
+ {
+ if (! updateChildren(ec, ev, vf))
+ ec = null;
+ }
forwardUpdate(ec, ev, shape, vf);
updateLayout(ec, ev, shape);
}
@@ -426,12 +429,18 @@ public abstract class View implements SwingConstants
*/
public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf)
{
- Element el = getElement();
- DocumentEvent.ElementChange ec = ev.getChange(el);
- if (ec != null)
- updateChildren(ec, ev, vf);
- forwardUpdate(ec, ev, shape, vf);
- updateLayout(ec, ev, shape);
+ if (getViewCount() > 0)
+ {
+ Element el = getElement();
+ DocumentEvent.ElementChange ec = ev.getChange(el);
+ if (ec != null)
+ {
+ if (! updateChildren(ec, ev, vf))
+ ec = null;
+ }
+ forwardUpdate(ec, ev, shape, vf);
+ updateLayout(ec, ev, shape);
+ }
}
/**
@@ -493,27 +502,66 @@ public abstract class View implements SwingConstants
int count = getViewCount();
if (count > 0)
{
+ // Determine start index.
int startOffset = ev.getOffset();
- int endOffset = startOffset + ev.getLength();
int startIndex = getViewIndex(startOffset, Position.Bias.Backward);
- int endIndex = getViewIndex(endOffset, Position.Bias.Forward);
- int index = -1;
- int addLength = -1;
- if (ec != null)
+
+ // For REMOVE events we have to forward the event to the last element,
+ // for the case that an Element has been removed that represente
+ // the offset.
+ if (startIndex == -1 && ev.getType() == DocumentEvent.EventType.REMOVE
+ && startOffset >= getEndOffset())
{
- index = ec.getIndex();
- addLength = ec.getChildrenAdded().length;
+ startIndex = getViewCount() - 1;
}
- if (startIndex >= 0 && endIndex >= 0)
+ // When startIndex is on a view boundary, forward event to the
+ // previous view too.
+ if (startIndex >= 0)
{
- for (int i = startIndex; i <= endIndex; i++)
+ View v = getView(startIndex);
+ if (v != null)
+ {
+ if (v.getStartOffset() == startOffset && startOffset > 0)
+ startIndex = Math.max(0, startIndex - 1);
+ }
+ }
+ startIndex = Math.max(0, startIndex);
+
+ // Determine end index.
+ int endIndex = startIndex;
+ if (ev.getType() != DocumentEvent.EventType.REMOVE)
+ {
+ endIndex = getViewIndex(startOffset + ev.getLength(),
+ Position.Bias.Forward);
+ if (endIndex < 0)
+ endIndex = getViewCount() - 1;
+ }
+
+ // Determine hole that comes from added elements (we don't forward
+ // the event to newly added views.
+ int startAdded = endIndex + 1;
+ int endAdded = startAdded;
+ Element[] added = (ec != null) ? ec.getChildrenAdded() : null;
+ if (added != null && added.length > 0)
+ {
+ startAdded = ec.getIndex();
+ endAdded = startAdded + added.length - 1;
+ }
+
+ // Forward event to all views between startIndex and endIndex,
+ // and leave out all views in the hole.
+ for (int i = startIndex; i <= endIndex; i++)
+ {
+ // Skip newly added child views.
+ if (! (i >= startAdded && i <= endAdded))
{
- // Skip newly added child views.
- if (index >= 0 && i >= index && i < (index+addLength))
- continue;
View child = getView(i);
- forwardUpdateToView(child, ev, shape, vf);
+ if (child != null)
+ {
+ Shape childAlloc = getChildAllocation(i, shape);
+ forwardUpdateToView(child, ev, childAlloc, vf);
+ }
}
}
}
@@ -611,9 +659,46 @@ public abstract class View implements SwingConstants
if (b2 != Position.Bias.Forward && b2 != Position.Bias.Backward)
throw new IllegalArgumentException
("b2 must be either Position.Bias.Forward or Position.Bias.Backward");
- Rectangle s1 = (Rectangle) modelToView(p1, a, b1);
- Rectangle s2 = (Rectangle) modelToView(p2, a, b2);
- return SwingUtilities.computeUnion(s1.x, s1.y, s1.width, s1.height, s2);
+
+ Shape s1 = modelToView(p1, a, b1);
+ // Special case for p2 == end index.
+ Shape s2;
+ if (p2 != getEndOffset())
+ {
+ s2 = modelToView(p2, a, b2);
+ }
+ else
+ {
+ try
+ {
+ s2 = modelToView(p2, a, b2);
+ }
+ catch (BadLocationException ex)
+ {
+ // Assume the end rectangle to be at the right edge of the
+ // view.
+ Rectangle aRect = a instanceof Rectangle ? (Rectangle) a
+ : a.getBounds();
+ s2 = new Rectangle(aRect.x + aRect.width - 1, aRect.y, 1,
+ aRect.height);
+ }
+ }
+
+ // Need to modify the rectangle, so we create a copy in all cases.
+ Rectangle r1 = s1.getBounds();
+ Rectangle r2 = s2 instanceof Rectangle ? (Rectangle) s2
+ : s2.getBounds();
+
+ // For multiline view, let the resulting rectangle span the whole view.
+ if (r1.y != r2.y)
+ {
+ Rectangle aRect = a instanceof Rectangle ? (Rectangle) a
+ : a.getBounds();
+ r1.x = aRect.x;
+ r1.width = aRect.width;
+ }
+
+ return SwingUtilities.computeUnion(r2.x, r2.y, r2.width, r2.height, r1);
}
/**
diff --git a/javax/swing/text/WrappedPlainView.java b/javax/swing/text/WrappedPlainView.java
index a6c369a4c..8cb2f4fb5 100644
--- a/javax/swing/text/WrappedPlainView.java
+++ b/javax/swing/text/WrappedPlainView.java
@@ -449,10 +449,34 @@ public class WrappedPlainView extends BoxView implements TabExpander
int currStart = getStartOffset();
int currEnd;
int count = 0;
+
+ // Determine layered highlights.
+ Container c = getContainer();
+ LayeredHighlighter lh = null;
+ JTextComponent tc = null;
+ if (c instanceof JTextComponent)
+ {
+ tc = (JTextComponent) c;
+ Highlighter h = tc.getHighlighter();
+ if (h instanceof LayeredHighlighter)
+ lh = (LayeredHighlighter) h;
+ }
+
while (currStart < end)
{
currEnd = calculateBreakPosition(currStart, end);
+ // Paint layered highlights, if any.
+ if (lh != null)
+ {
+ // Exclude trailing newline in last line.
+ if (currEnd == end)
+ lh.paintLayeredHighlights(g, currStart, currEnd - 1, s, tc,
+ this);
+ else
+ lh.paintLayeredHighlights(g, currStart, currEnd, s, tc, this);
+
+ }
drawLine(currStart, currEnd, g, rect.x, rect.y + metrics.getAscent());
rect.y += lineHeight;
diff --git a/javax/swing/text/html/HTMLDocument.java b/javax/swing/text/html/HTMLDocument.java
index 0eaf66fd8..0bfc338df 100644
--- a/javax/swing/text/html/HTMLDocument.java
+++ b/javax/swing/text/html/HTMLDocument.java
@@ -40,14 +40,18 @@ package javax.swing.text.html;
import gnu.classpath.NotImplementedException;
import gnu.javax.swing.text.html.CharacterAttributeTranslator;
+import gnu.javax.swing.text.html.parser.htmlAttributeSet;
import java.io.IOException;
+import java.io.StringReader;
import java.net.URL;
import java.util.HashMap;
import java.util.Stack;
import java.util.Vector;
import javax.swing.JEditorPane;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.HyperlinkEvent.EventType;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
@@ -515,19 +519,23 @@ public class HTMLDocument extends DefaultStyledDocument
*/
public class HTMLReader extends HTMLEditorKit.ParserCallback
{
- /** Holds the current character attribute set **/
+ /**
+ * Holds the current character attribute set *
+ */
protected MutableAttributeSet charAttr = new SimpleAttributeSet();
protected Vector parseBuffer = new Vector();
- /** A stack for character attribute sets **/
+ /**
+ * A stack for character attribute sets *
+ */
Stack charAttrStack = new Stack();
/**
* The parse stack. This stack holds HTML.Tag objects that reflect the
* current position in the parsing process.
*/
- private Stack parseStack = new Stack();
+ Stack parseStack = new Stack();
/** A mapping between HTML.Tag objects and the actions that handle them **/
HashMap tagToAction;
@@ -535,10 +543,31 @@ public class HTMLDocument extends DefaultStyledDocument
/** Tells us whether we've received the '</html>' tag yet **/
boolean endHTMLEncountered = false;
- /** Variables related to the constructor with explicit insertTag **/
- int popDepth, pushDepth, offset;
+ /**
+ * Related to the constructor with explicit insertTag
+ */
+ int popDepth;
+
+ /**
+ * Related to the constructor with explicit insertTag
+ */
+ int pushDepth;
+
+ /**
+ * Related to the constructor with explicit insertTag
+ */
+ int offset;
+
+ /**
+ * The tag (inclusve), after that the insertion should start.
+ */
HTML.Tag insertTag;
- boolean insertTagEncountered = false;
+
+ /**
+ * This variable becomes true after the insert tag has been encountered.
+ */
+ boolean insertTagEncountered;
+
/** A temporary variable that helps with the printing out of debug information **/
boolean debug = false;
@@ -1139,8 +1168,21 @@ public class HTMLDocument extends DefaultStyledDocument
}
/**
- * This method is called by the parser and should route the call to
- * the proper handler for the tag.
+ * Checks if the HTML tag should be inserted. The tags before insert tag (if
+ * specified) are not inserted. Also, the tags after the end of the html are
+ * not inserted.
+ *
+ * @return true if the tag should be inserted, false otherwise.
+ */
+ private boolean shouldInsert()
+ {
+ return ! endHTMLEncountered
+ && (insertTagEncountered || insertTag == null);
+ }
+
+ /**
+ * This method is called by the parser and should route the call to the
+ * proper handler for the tag.
*
* @param t the HTML.Tag
* @param a the attribute set
@@ -1148,13 +1190,15 @@ public class HTMLDocument extends DefaultStyledDocument
*/
public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos)
{
- // Don't call the Action if we've already seen </html>.
- if (endHTMLEncountered)
- return;
-
- TagAction action = (TagAction) tagToAction.get(t);
- if (action != null)
- action.start(t, a);
+ if (t == insertTag)
+ insertTagEncountered = true;
+
+ if (shouldInsert())
+ {
+ TagAction action = (TagAction) tagToAction.get(t);
+ if (action != null)
+ action.start(t, a);
+ }
}
/**
@@ -1165,42 +1209,41 @@ public class HTMLDocument extends DefaultStyledDocument
*/
public void handleComment(char[] data, int pos)
{
- // Don't call the Action if we've already seen </html>.
- if (endHTMLEncountered)
- return;
-
- TagAction action = (TagAction) tagToAction.get(HTML.Tag.COMMENT);
- if (action != null)
+ if (shouldInsert())
{
- action.start(HTML.Tag.COMMENT, new SimpleAttributeSet());
- action.end (HTML.Tag.COMMENT);
+ TagAction action = (TagAction) tagToAction.get(HTML.Tag.COMMENT);
+ if (action != null)
+ {
+ action.start(HTML.Tag.COMMENT,
+ htmlAttributeSet.EMPTY_HTML_ATTRIBUTE_SET);
+ action.end(HTML.Tag.COMMENT);
+ }
}
}
/**
- * This method is called by the parser and should route the call to
- * the proper handler for the tag.
+ * This method is called by the parser and should route the call to the
+ * proper handler for the tag.
*
* @param t the HTML.Tag
* @param pos the position at which the tag was encountered
*/
public void handleEndTag(HTML.Tag t, int pos)
{
- // Don't call the Action if we've already seen </html>.
- if (endHTMLEncountered)
- return;
-
- // If this is the </html> tag we need to stop calling the Actions
- if (t == HTML.Tag.HTML)
- endHTMLEncountered = true;
-
- TagAction action = (TagAction) tagToAction.get(t);
- if (action != null)
- action.end(t);
+ if (shouldInsert())
+ {
+ // If this is the </html> tag we need to stop calling the Actions
+ if (t == HTML.Tag.HTML)
+ endHTMLEncountered = true;
+
+ TagAction action = (TagAction) tagToAction.get(t);
+ if (action != null)
+ action.end(t);
+ }
}
/**
- * This is a callback from the parser that should be routed to the
+ * This is a callback from the parser that should be routed to the
* appropriate handler for the tag.
*
* @param t the HTML.Tag that was encountered
@@ -1209,15 +1252,17 @@ public class HTMLDocument extends DefaultStyledDocument
*/
public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos)
{
- // Don't call the Action if we've already seen </html>.
- if (endHTMLEncountered)
- return;
-
- TagAction action = (TagAction) tagToAction.get (t);
- if (action != null)
+ if (t == insertTag)
+ insertTagEncountered = true;
+
+ if (shouldInsert())
{
- action.start(t, a);
- action.end(t);
+ TagAction action = (TagAction) tagToAction.get(t);
+ if (action != null)
+ {
+ action.start(t, a);
+ action.end(t);
+ }
}
}
@@ -1230,7 +1275,6 @@ public class HTMLDocument extends DefaultStyledDocument
* @since 1.3
*/
public void handleEndOfLineString(String eol)
- throws NotImplementedException
{
// FIXME: Implement.
print ("HTMLReader.handleEndOfLineString not implemented yet");
@@ -1273,16 +1317,6 @@ public class HTMLDocument extends DefaultStyledDocument
printBuffer();
DefaultStyledDocument.ElementSpec element;
- // If the previous tag is content and the parent is p-implied, then
- // we must also close the p-implied.
- if (parseStack.size() > 0 && parseStack.peek() == HTML.Tag.IMPLIED)
- {
- element = new DefaultStyledDocument.ElementSpec(null,
- DefaultStyledDocument.ElementSpec.EndTagType);
- parseBuffer.addElement(element);
- parseStack.pop();
- }
-
parseStack.push(t);
AbstractDocument.AttributeContext ctx = getAttributeContext();
AttributeSet copy = attr.copyAttributes();
@@ -1320,16 +1354,6 @@ public class HTMLDocument extends DefaultStyledDocument
new char[0], 0, 0);
parseBuffer.add(element);
}
- // If the previous tag is content and the parent is p-implied, then
- // we must also close the p-implied.
- else if (parseStack.peek() == HTML.Tag.IMPLIED)
- {
- element = new DefaultStyledDocument.ElementSpec(null,
- DefaultStyledDocument.ElementSpec.EndTagType);
- parseBuffer.addElement(element);
- if (parseStack.size() > 0)
- parseStack.pop();
- }
element = new DefaultStyledDocument.ElementSpec(null,
DefaultStyledDocument.ElementSpec.EndTagType);
@@ -1369,27 +1393,6 @@ public class HTMLDocument extends DefaultStyledDocument
DefaultStyledDocument.ElementSpec element;
AttributeSet attributes = null;
- // Content must always be embedded inside a paragraph element,
- // so we create this if the previous element is not one of
- // <p>, <h1> .. <h6>.
- boolean createImpliedParagraph = false;
- HTML.Tag parent = (HTML.Tag) parseStack.peek();
- if (parent != HTML.Tag.P && parent != HTML.Tag.H1
- && parent != HTML.Tag.H2
- && parent != HTML.Tag.H3 && parent != HTML.Tag.H4
- && parent != HTML.Tag.H5 && parent != HTML.Tag.H6
- && parent != HTML.Tag.TD)
- {
- attributes = ctx.getEmptySet();
- attributes = ctx.addAttribute(attributes,
- StyleConstants.NameAttribute,
- HTML.Tag.IMPLIED);
- element = new DefaultStyledDocument.ElementSpec(attributes,
- DefaultStyledDocument.ElementSpec.StartTagType);
- parseBuffer.add(element);
- parseStack.push(HTML.Tag.IMPLIED);
- }
-
// Copy the attribute set, don't use the same object because
// it may change
if (charAttr != null)
@@ -1481,7 +1484,61 @@ public class HTMLDocument extends DefaultStyledDocument
HTML.Tag insertTag)
{
return new HTMLReader(pos, popDepth, pushDepth, insertTag);
- }
+ }
+
+ /**
+ * Gets the reader for the parser to use when inserting the HTML fragment into
+ * the document. Checks if the parser is present, sets the parent in the
+ * element stack and removes any actions for BODY (it can be only one body in
+ * a HTMLDocument).
+ *
+ * @param pos - the starting position
+ * @param popDepth - the number of EndTagTypes to generate before inserting
+ * @param pushDepth - the number of StartTagTypes with a direction of
+ * JoinNextDirection that should be generated before inserting, but
+ * after the end tags have been generated.
+ * @param insertTag - the first tag to start inserting into document
+ * @param parent the element that will be the parent in the document. HTML
+ * parsing includes checks for the parent, so it must be available.
+ * @return - the reader
+ * @throws IllegalStateException if the parsert is not set.
+ */
+ public HTMLEditorKit.ParserCallback getInsertingReader(int pos, int popDepth,
+ int pushDepth,
+ HTML.Tag insertTag,
+ final Element parent)
+ throws IllegalStateException
+ {
+ if (parser == null)
+ throw new IllegalStateException("Parser has not been set");
+
+ HTMLReader reader = new HTMLReader(pos, popDepth, pushDepth, insertTag)
+ {
+ /**
+ * Ignore BODY.
+ */
+ public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos)
+ {
+ if (t != HTML.Tag.BODY)
+ super.handleStartTag(t, a, pos);
+ }
+
+ /**
+ * Ignore BODY.
+ */
+ public void handleEndTag(HTML.Tag t, int pos)
+ {
+ if (t != HTML.Tag.BODY)
+ super.handleEndTag(t, pos);
+ }
+ };
+
+ // Set the parent HTML tag.
+ reader.parseStack.push(parent.getAttributes().getAttribute(
+ StyleConstants.NameAttribute));
+
+ return reader;
+ }
/**
* Gets the child element that contains the attribute with the value or null.
@@ -1490,8 +1547,8 @@ public class HTMLDocument extends DefaultStyledDocument
* @param e - the element to begin search at
* @param attribute - the desired attribute
* @param value - the desired value
- * @return the element found with the attribute and value specified or null
- * if it is not found.
+ * @return the element found with the attribute and value specified or null if
+ * it is not found.
*/
public Element getElement(Element e, Object attribute, Object value)
{
@@ -1516,16 +1573,17 @@ public class HTMLDocument extends DefaultStyledDocument
}
/**
- * Returns the element that has the given id Attribute. If it is not found,
- * null is returned. This method works on an Attribute, not a character tag.
- * This is not thread-safe.
+ * Returns the element that has the given id Attribute (for instance, &lt;p id
+ * ='my paragraph &gt;'). If it is not found, null is returned. The HTML tag,
+ * having this attribute, is not checked by this method and can be any. The
+ * method is not thread-safe.
*
- * @param attrId - the Attribute id to look for
+ * @param attrId - the value of the attribute id to look for
* @return the element that has the given id.
*/
public Element getElement(String attrId)
{
- return getElement(getDefaultRootElement(), HTML.getAttributeKey(attrId),
+ return getElement(getDefaultRootElement(), HTML.Attribute.ID,
attrId);
}
@@ -1542,22 +1600,30 @@ public class HTMLDocument extends DefaultStyledDocument
* @throws IllegalStateException - if an HTMLEditorKit.Parser has not been set
*/
public void setInnerHTML(Element elem, String htmlText)
- throws BadLocationException, IOException, NotImplementedException
+ throws BadLocationException, IOException
{
if (elem.isLeaf())
throw new IllegalArgumentException("Element is a leaf");
- if (parser == null)
- throw new IllegalStateException("Parser has not been set");
- // FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
- System.out.println("setInnerHTML not implemented");
+
+ int start = elem.getStartOffset();
+ int end = elem.getEndOffset();
+
+ HTMLEditorKit.ParserCallback reader = getInsertingReader(
+ end, 0, 0, HTML.Tag.BODY, elem);
+
+ // TODO charset
+ getParser().parse(new StringReader(htmlText), reader, true);
+
+ // Remove the previous content
+ remove(start, end - start);
}
/**
- * Replaces the given element in the parent with the string. When replacing
- * a leaf, this will attempt to make sure there is a newline present if one is
- * needed. This may result in an additional element being inserted.
- * This will be seen as at least two events, n inserts followed by a remove.
- * The HTMLEditorKit.Parser must be set.
+ * Replaces the given element in the parent with the string. When replacing a
+ * leaf, this will attempt to make sure there is a newline present if one is
+ * needed. This may result in an additional element being inserted. This will
+ * be seen as at least two events, n inserts followed by a remove. The
+ * HTMLEditorKit.Parser must be set.
*
* @param elem - the branch element whose parent will be replaced
* @param htmlText - the string to be parsed and assigned to elem
@@ -1565,18 +1631,25 @@ public class HTMLDocument extends DefaultStyledDocument
* @throws IOException
* @throws IllegalStateException - if parser is not set
*/
- public void setOuterHTML(Element elem, String htmlText)
- throws BadLocationException, IOException, NotImplementedException
- {
- if (parser == null)
- throw new IllegalStateException("Parser has not been set");
- // FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
- System.out.println("setOuterHTML not implemented");
- }
+public void setOuterHTML(Element elem, String htmlText)
+ throws BadLocationException, IOException
+ {
+ // Remove the current element:
+ int start = elem.getStartOffset();
+ int end = elem.getEndOffset();
+
+ remove(start, end-start);
+
+ HTMLEditorKit.ParserCallback reader = getInsertingReader(
+ start, 0, 0, HTML.Tag.BODY, elem);
+
+ // TODO charset
+ getParser().parse(new StringReader(htmlText), reader, true);
+ }
/**
- * Inserts the string before the start of the given element.
- * The parser must be set.
+ * Inserts the string before the start of the given element. The parser must
+ * be set.
*
* @param elem - the element to be the root for the new text.
* @param htmlText - the string to be parsed and assigned to elem
@@ -1585,18 +1658,19 @@ public class HTMLDocument extends DefaultStyledDocument
* @throws IllegalStateException - if parser has not been set
*/
public void insertBeforeStart(Element elem, String htmlText)
- throws BadLocationException, IOException, NotImplementedException
+ throws BadLocationException, IOException
{
- if (parser == null)
- throw new IllegalStateException("Parser has not been set");
- // FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
- System.out.println("insertBeforeStart not implemented");
+ HTMLEditorKit.ParserCallback reader = getInsertingReader(
+ elem.getStartOffset(), 0, 0, HTML.Tag.BODY, elem);
+
+ // TODO charset
+ getParser().parse(new StringReader(htmlText), reader, true);
}
/**
- * Inserts the string at the end of the element. If elem's children
- * are leaves, and the character at elem.getEndOffset() - 1 is a newline,
- * then it will be inserted before the newline. The parser must be set.
+ * Inserts the string at the end of the element. If elem's children are
+ * leaves, and the character at elem.getEndOffset() - 1 is a newline, then it
+ * will be inserted before the newline. The parser must be set.
*
* @param elem - the element to be the root for the new text
* @param htmlText - the text to insert
@@ -1605,12 +1679,14 @@ public class HTMLDocument extends DefaultStyledDocument
* @throws IllegalStateException - if parser is not set
*/
public void insertBeforeEnd(Element elem, String htmlText)
- throws BadLocationException, IOException, NotImplementedException
+ throws BadLocationException, IOException
{
- if (parser == null)
- throw new IllegalStateException("Parser has not been set");
- // FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
- System.out.println("insertBeforeEnd not implemented");
+ HTMLEditorKit.ParserCallback reader = getInsertingReader(
+ elem.getEndOffset(), 0, 0, HTML.Tag.BODY, elem);
+
+ // TODO charset
+ getParser().parse(new StringReader(htmlText), reader, true);
+
}
/**
@@ -1624,12 +1700,13 @@ public class HTMLDocument extends DefaultStyledDocument
* @throws IllegalStateException - if parser is not set
*/
public void insertAfterEnd(Element elem, String htmlText)
- throws BadLocationException, IOException, NotImplementedException
+ throws BadLocationException, IOException
{
- if (parser == null)
- throw new IllegalStateException("Parser has not been set");
- // FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
- System.out.println("insertAfterEnd not implemented");
+ HTMLEditorKit.ParserCallback reader = getInsertingReader(
+ elem.getEndOffset(), 0, 0, HTML.Tag.BODY, elem);
+
+ // TODO charset
+ getParser().parse(new StringReader(htmlText), reader, true);
}
/**
@@ -1643,11 +1720,12 @@ public class HTMLDocument extends DefaultStyledDocument
* @throws IllegalStateException - if parser is not set
*/
public void insertAfterStart(Element elem, String htmlText)
- throws BadLocationException, IOException, NotImplementedException
+ throws BadLocationException, IOException
{
- if (parser == null)
- throw new IllegalStateException("Parser has not been set");
- // FIXME: Not implemented fully, use InsertHTML* in HTMLEditorKit?
- System.out.println("insertAfterStart not implemented");
+ HTMLEditorKit.ParserCallback reader = getInsertingReader(
+ elem.getStartOffset(), 0, 0, HTML.Tag.BODY, elem);
+
+ // TODO charset
+ getParser().parse(new StringReader(htmlText), reader, true);
}
}
diff --git a/javax/swing/text/html/HTMLEditorKit.java b/javax/swing/text/html/HTMLEditorKit.java
index 7addfb365..5d77be8fd 100644
--- a/javax/swing/text/html/HTMLEditorKit.java
+++ b/javax/swing/text/html/HTMLEditorKit.java
@@ -71,6 +71,11 @@ import javax.swing.text.View;
import javax.swing.text.ViewFactory;
import javax.swing.text.html.parser.ParserDelegator;
+/* Move these imports here after javax.swing.text.html to make it compile
+ with jikes. */
+import gnu.javax.swing.text.html.parser.GnuParserDelegator;
+import gnu.javax.swing.text.html.parser.HTML_401Swing;
+
/**
* @author Lillian Angel (langel at redhat dot com)
*/
@@ -886,7 +891,9 @@ public class HTMLEditorKit
protected Parser getParser()
{
if (parser == null)
- parser = new ParserDelegator();
+ {
+ parser = new GnuParserDelegator(HTML_401Swing.getInstance());
+ }
return parser;
}
diff --git a/javax/swing/text/html/parser/ParserDelegator.java b/javax/swing/text/html/parser/ParserDelegator.java
index e5d2db4df..70636d929 100644
--- a/javax/swing/text/html/parser/ParserDelegator.java
+++ b/javax/swing/text/html/parser/ParserDelegator.java
@@ -52,9 +52,6 @@ import javax.swing.text.html.HTMLEditorKit.ParserCallback;
* This class instantiates and starts the working instance of
* html parser, being responsible for providing the default DTD.
*
- * TODO Later this class must be derived from the totally abstract class
- * HTMLEditorKit.Parser. HTMLEditorKit that does not yet exist.
- *
* @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
*/
public class ParserDelegator
diff --git a/javax/swing/tree/TreePath.java b/javax/swing/tree/TreePath.java
index 93b59b07e..1c4d78787 100644
--- a/javax/swing/tree/TreePath.java
+++ b/javax/swing/tree/TreePath.java
@@ -174,7 +174,7 @@ public class TreePath implements Serializable
return false;
for (index = 0; index < path.length; index++)
{
- if (!treepath[index].equals(path[index]))
+ if (!path[index].equals(treepath[index]))
return false;
}
diff --git a/javax/swing/tree/VariableHeightLayoutCache.java b/javax/swing/tree/VariableHeightLayoutCache.java
index 0a787f7ca..1b85fb13d 100644
--- a/javax/swing/tree/VariableHeightLayoutCache.java
+++ b/javax/swing/tree/VariableHeightLayoutCache.java
@@ -451,8 +451,8 @@ public class VariableHeightLayoutCache
{
if (y < r.y)
return r.y - y;
- else if (y > r.y + r.height)
- return y - (r.y + r.height);
+ else if (y > r.y + r.height - 1)
+ return y - (r.y + r.height - 1);
else
return 0;
}
diff --git a/lib/.cvsignore b/lib/.cvsignore
index e746f2bf6..56b990b49 100644
--- a/lib/.cvsignore
+++ b/lib/.cvsignore
@@ -34,3 +34,4 @@ Makefile.deps
lists
copy-vmresources.sh
classes.2
+standard.omit
diff --git a/lib/Makefile.am b/lib/Makefile.am
index c0f93e7a8..fc1081d03 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -44,9 +44,9 @@ COLLECTIONS = collections.jar
collections.jar: mkcollections.pl
./mkcollections.pl $(top_srcdir)
if FOUND_GCJ
- $(GCJ) -C `$(FIND) $(COLLECTIONS_PREFIX) -name '*' -type f -print`
+ $(GCJ) -C `$(FIND) $(COLLECTIONS_PREFIX) -name '*.java' -type f -print`
else
- $(JAVAC) `$(FIND) $(COLLECTIONS_PREFIX) -name '*' -type f -print`
+ $(JAVAC) `$(FIND) $(COLLECTIONS_PREFIX) -name '*.java' -type f -print`
endif
if test "$(FASTJAR)" != ""; then \
$(FASTJAR) cf $@ $(COLLECTIONS_PREFIX); \
diff --git a/lib/mkcollections.pl.in b/lib/mkcollections.pl.in
index bd00f01f2..3d2d3c78a 100755
--- a/lib/mkcollections.pl.in
+++ b/lib/mkcollections.pl.in
@@ -25,7 +25,8 @@
my $destpath=@COLLECTIONS_PREFIX@;
my $classpath=pop;
my @javalangclasses=qw(UnsupportedOperationException
- Comparable);
+ Comparable
+ Iterable);
my @javautilclasses=qw(AbstractCollection
AbstractList
AbstractMap
diff --git a/native/jawt/Makefile.am b/native/jawt/Makefile.am
index 01abf3bb9..c81e75429 100644
--- a/native/jawt/Makefile.am
+++ b/native/jawt/Makefile.am
@@ -2,6 +2,7 @@ nativeexeclib_LTLIBRARIES = libjawt.la
libjawt_la_SOURCES = jawt.c
libjawt_la_LIBADD = $(top_builddir)/native/jni/gtk-peer/libgtkpeer.la
+libjawt_la_LDFLAGS = -avoid-version
AM_LDFLAGS = @CLASSPATH_MODULE@ @GTK_LIBS@ @PANGOFT2_LIBS@ @X_LIBS@ @XTEST_LIBS@
AM_CPPFLAGS = @CLASSPATH_INCLUDES@
diff --git a/native/jni/gconf-peer/GConfNativePeer.c b/native/jni/gconf-peer/GConfNativePeer.c
index 55989f059..a442226ca 100644
--- a/native/jni/gconf-peer/GConfNativePeer.c
+++ b/native/jni/gconf-peer/GConfNativePeer.c
@@ -41,6 +41,7 @@
#include <jni.h>
#include <glib.h>
+#include <gdk/gdk.h>
#include <gconf/gconf-client.h>
#include "jcl.h"
@@ -72,30 +73,31 @@ static jmethodID jlist_add_id = NULL;
* Gets the reference of the default GConfClient and initialize the
* the type system.
* The client reference should be released with g_object_unref after use.
+ * This functions must be called with gdk lock held.
*/
static void init_gconf_client (void);
/**
* Throws a new runtime exception after a failure, with the given message.
*/
-static void throw_exception (JNIEnv *env, const char *msg);
+static void throw_exception (JNIEnv * env, const char *msg);
/**
* Throws the given exception after a failure, with the given message.
*/
static void
-throw_exception_by_name (JNIEnv *env, const char *name, const char *msg);
+throw_exception_by_name (JNIEnv * env, const char *name, const char *msg);
/**
* Return a reference to a java.util.ArrayList class.
*/
-static gboolean set_jlist_class (JNIEnv *env);
+static gboolean set_jlist_class (JNIEnv * env);
/**
* Builds a new reference to a new java.util.ArrayList instace.
* The instance should be freed by the caller after use.
*/
-static jclass get_jlist_reference (JNIEnv *env, jclass jlist_class);
+static jclass get_jlist_reference (JNIEnv * env, jclass jlist_class);
/* ***** END: PRIVATE FUNCTIONS DELCARATION ***** */
@@ -108,16 +110,17 @@ static jclass get_jlist_reference (JNIEnv *env, jclass jlist_class);
*/
JNIEXPORT void
JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_init_1class
- (JNIEnv *env, jclass clazz)
+ (JNIEnv *env, jclass clazz)
{
- if (reference_count == 0) {
- Java_gnu_java_util_prefs_gconf_GConfNativePeer_init_1id_1cache
- (env, clazz);
- return;
- }
-
- reference_count++;
-} /* Java_gnu_java_util_prefs_gconf_GConfNativePeer_init_1class */
+ if (reference_count == 0)
+ {
+ Java_gnu_java_util_prefs_gconf_GConfNativePeer_init_1id_1cache
+ (env, clazz);
+ return;
+ }
+
+ reference_count++;
+}
/*
* Class: gnu_java_util_prefs_gconf_GConfNativePeer
@@ -126,27 +129,31 @@ JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_init_1class
*/
JNIEXPORT void
JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_init_1id_1cache
- (JNIEnv *env, jclass clazz __attribute__ ((unused)))
+ (JNIEnv *env, jclass clazz __attribute__ ((unused)))
{
- reference_count++;
+ reference_count++;
+
+ gdk_threads_enter ();
+ init_gconf_client ();
+ gdk_threads_leave ();
+
+ /* if client is null, there is probably an out of memory */
+ if (client == NULL)
+ {
+ /* release the string and throw a runtime exception */
+ throw_exception (env,
+ "Unable to initialize GConfClient in native code\n");
+ return;
+ }
- init_gconf_client ();
-
- /* if client is null, there is probably an out or memory */
- if (client == NULL) {
- /* release the string and throw a runtime exception */
- throw_exception (env,
- "Unable to initialize GConfClient in native code\n");
- return;
- }
-
- /* ***** java.util.ArrayList ***** */
- if (set_jlist_class (env) == FALSE) {
- throw_exception (env,
- "Unable to get valid reference to java.util.List in native code\n");
- return;
- }
-} /* Java_gnu_java_util_prefs_gconf_GConfNativePeer_init_1id_1cache */
+ /* ***** java.util.ArrayList ***** */
+ if (set_jlist_class (env) == FALSE)
+ {
+ throw_exception (env,
+ "Unable to get valid reference to java.util.List in native code\n");
+ return;
+ }
+}
/*
* Class: gnu_java_util_prefs_gconf_GConfNativePeer
@@ -155,58 +162,67 @@ JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_init_1id_1cache
*/
JNIEXPORT jobject JNICALL
Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1gconf_1client_1all_1keys
- (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring node)
+ (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring node)
{
- const char *dir = NULL;
- GError *err = NULL;
- GSList *entries = NULL;
- GSList *tmp;
-
- /* java.util.ArrayList */
- jobject jlist = NULL;
-
- dir = JCL_jstring_to_cstring(env, node);
- if (dir == NULL) {
- return NULL;
- }
-
- entries = gconf_client_all_entries (client, dir, &err);
- if (err != NULL) {
- throw_exception_by_name (env, "java/util/prefs/BackingStoreException",
- err->message);
- g_error_free (err);
- err = NULL;
-
- JCL_free_cstring(env, node, dir);
- return NULL;
- }
-
- jlist = get_jlist_reference (env, jlist_class);
- if (jlist == NULL) {
- throw_exception_by_name (env, "java/util/prefs/BackingStoreException",
- "Unable to get java.util.List reference in native code\n");
- JCL_free_cstring(env, node, dir);
- g_slist_foreach (entries, (GFunc) gconf_entry_free, NULL);
- g_slist_free (entries);
- return NULL;
- }
-
- tmp = entries;
- while (tmp != NULL) {
- const char *_val = gconf_entry_get_key(tmp->data);
- _val = strrchr (_val, '/'); ++_val;
- (*env)->CallBooleanMethod(env, jlist, jlist_add_id,
- (*env)->NewStringUTF(env, _val));
- tmp = g_slist_next (tmp);
- }
-
- /* clean up things */
- JCL_free_cstring(env, node, dir);
- g_slist_foreach (entries, (GFunc) gconf_entry_free, NULL);
- g_slist_free (entries);
-
- return jlist;
-} /* Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1gconf_1client_1all_1keys */
+ /* TODO: check all the calls to gdk_threads_enter/leave */
+
+ const char *dir = NULL;
+ GError *err = NULL;
+ GSList *entries = NULL;
+ GSList *tmp;
+
+ /* java.util.ArrayList */
+ jobject jlist = NULL;
+
+ dir = JCL_jstring_to_cstring (env, node);
+ if (dir == NULL)
+ {
+ return NULL;
+ }
+
+ gdk_threads_enter ();
+ entries = gconf_client_all_entries (client, dir, &err);
+ gdk_threads_leave ();
+ if (err != NULL)
+ {
+ throw_exception_by_name (env, "java/util/prefs/BackingStoreException",
+ err->message);
+ g_error_free (err);
+ err = NULL;
+
+ JCL_free_cstring (env, node, dir);
+ return NULL;
+ }
+
+ jlist = get_jlist_reference (env, jlist_class);
+ if (jlist == NULL)
+ {
+ throw_exception_by_name (env, "java/util/prefs/BackingStoreException",
+ "Unable to get java.util.List reference in native code\n");
+ JCL_free_cstring (env, node, dir);
+ g_slist_foreach (entries, (GFunc) gconf_entry_free, NULL);
+ g_slist_free (entries);
+ return NULL;
+ }
+
+ tmp = entries;
+ while (tmp != NULL)
+ {
+ const char *_val = gconf_entry_get_key (tmp->data);
+ _val = strrchr (_val, '/');
+ ++_val;
+ (*env)->CallBooleanMethod (env, jlist, jlist_add_id,
+ (*env)->NewStringUTF (env, _val));
+ tmp = g_slist_next (tmp);
+ }
+
+ /* clean up things */
+ JCL_free_cstring (env, node, dir);
+ g_slist_foreach (entries, (GFunc) gconf_entry_free, NULL);
+ g_slist_free (entries);
+
+ return jlist;
+}
/*
* Class: gnu_java_util_prefs_gconf_GConfNativePeer
@@ -215,57 +231,64 @@ Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1gconf_1client_1all
*/
JNIEXPORT jobject JNICALL
Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1gconf_1client_1all_1nodes
- (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring node)
+ (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring node)
{
- const char *dir = NULL;
- GError *err = NULL;
- GSList *entries = NULL;
- GSList *tmp;
-
- /* java.util.ArrayList */
- jobject jlist = NULL;
-
- dir = JCL_jstring_to_cstring(env, node);
- if (dir == NULL) {
- return NULL;
- }
-
- entries = gconf_client_all_dirs (client, dir, &err);
- if (err != NULL) {
- throw_exception_by_name (env, "java/util/prefs/BackingStoreException",
- err->message);
- g_error_free (err);
- err = NULL;
- JCL_free_cstring(env, node, dir);
- return NULL;
- }
-
- jlist = get_jlist_reference (env, jlist_class);
- if (jlist == NULL) {
- throw_exception_by_name (env, "java/util/prefs/BackingStoreException",
- "Unable to get java.util.List reference in native code\n");
- JCL_free_cstring(env, node, dir);
- g_slist_foreach (entries, (GFunc) gconf_entry_free, NULL);
- g_slist_free (entries);
- return NULL;
- }
-
- tmp = entries;
- while (tmp != NULL) {
- const char *_val = tmp->data;
- _val = strrchr (_val, '/'); ++_val;
- (*env)->CallBooleanMethod(env, jlist, jlist_add_id,
- (*env)->NewStringUTF(env, _val));
- tmp = g_slist_next (tmp);
- }
-
- /* clean up things */
- JCL_free_cstring(env, node, dir);
- g_slist_foreach (entries, (GFunc) gconf_entry_free, NULL);
- g_slist_free (entries);
-
- return jlist;
-} /* Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1gconf_1client_1all_1nodes */
+ const char *dir = NULL;
+ GError *err = NULL;
+ GSList *entries = NULL;
+ GSList *tmp;
+
+ /* java.util.ArrayList */
+ jobject jlist = NULL;
+
+ dir = JCL_jstring_to_cstring (env, node);
+ if (dir == NULL)
+ {
+ return NULL;
+ }
+
+ gdk_threads_enter ();
+ entries = gconf_client_all_dirs (client, dir, &err);
+ gdk_threads_leave ();
+ if (err != NULL)
+ {
+ throw_exception_by_name (env, "java/util/prefs/BackingStoreException",
+ err->message);
+ g_error_free (err);
+ err = NULL;
+ JCL_free_cstring (env, node, dir);
+ return NULL;
+ }
+
+ jlist = get_jlist_reference (env, jlist_class);
+ if (jlist == NULL)
+ {
+ throw_exception_by_name (env, "java/util/prefs/BackingStoreException",
+ "Unable to get java.util.List reference in native code\n");
+ JCL_free_cstring (env, node, dir);
+ g_slist_foreach (entries, (GFunc) gconf_entry_free, NULL);
+ g_slist_free (entries);
+ return NULL;
+ }
+
+ tmp = entries;
+ while (tmp != NULL)
+ {
+ const char *_val = tmp->data;
+ _val = strrchr (_val, '/');
+ ++_val;
+ (*env)->CallBooleanMethod (env, jlist, jlist_add_id,
+ (*env)->NewStringUTF (env, _val));
+ tmp = g_slist_next (tmp);
+ }
+
+ /* clean up things */
+ JCL_free_cstring (env, node, dir);
+ g_slist_foreach (entries, (GFunc) gconf_entry_free, NULL);
+ g_slist_free (entries);
+
+ return jlist;
+}
/*
* Class: gnu_java_util_prefs_gconf_GConfNativePeer
@@ -274,18 +297,21 @@ Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1gconf_1client_1all
*/
JNIEXPORT void JNICALL
Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1suggest_1sync
- (JNIEnv *env, jclass clazz __attribute__ ((unused)))
+ (JNIEnv *env, jclass clazz __attribute__ ((unused)))
{
- GError *err = NULL;
-
- gconf_client_suggest_sync (client, &err);
- if (err != NULL) {
- throw_exception_by_name (env, "java/util/prefs/BackingStoreException",
- err->message);
- g_error_free (err);
- err = NULL;
- }
-} /* Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1suggest_1sync */
+ GError *err = NULL;
+
+ gdk_threads_enter ();
+ gconf_client_suggest_sync (client, &err);
+ gdk_threads_leave ();
+ if (err != NULL)
+ {
+ throw_exception_by_name (env, "java/util/prefs/BackingStoreException",
+ err->message);
+ g_error_free (err);
+ err = NULL;
+ }
+}
/*
* Class: gnu_java_util_prefs_gconf_GConfNativePeer
@@ -294,22 +320,32 @@ Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1suggest_1sync
*/
JNIEXPORT jboolean JNICALL
Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1unset
- (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring key)
+ (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring key)
{
- const char *_key = NULL;
- gboolean result = JNI_FALSE;
-
- _key = JCL_jstring_to_cstring(env, key);
- if (_key == NULL) {
- return JNI_FALSE;
- }
-
- result = gconf_client_unset (client, _key, NULL);
-
- JCL_free_cstring(env, key, _key);
+ const char *_key = NULL;
+ gboolean result = JNI_FALSE;
+ GError *err = NULL;
+
+ _key = JCL_jstring_to_cstring (env, key);
+ if (_key == NULL)
+ {
+ return JNI_FALSE;
+ }
+
+ gdk_threads_enter ();
+ result = gconf_client_unset (client, _key, &err);
+ gdk_threads_leave ();
+ if (err != NULL)
+ {
+ result = JNI_FALSE;
+ g_error_free (err);
+ err = NULL;
+ }
+
+ JCL_free_cstring (env, key, _key);
- return result;
-} /* Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1unset */
+ return result;
+}
/*
* Class: gnu_java_util_prefs_gconf_GConfNativePeer
@@ -318,25 +354,43 @@ Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1unset
*/
JNIEXPORT jstring JNICALL
Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1get_1string
- (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring key)
+ (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring key)
{
- const char *_key = NULL;
- const char *_value = NULL;
- jstring result = NULL;
-
- _key = JCL_jstring_to_cstring(env, key);
- if (_key == NULL) {
- return NULL;
- }
-
- _value = gconf_client_get_string (client, _key, NULL);
- JCL_free_cstring(env, key, _key);
-
- result = (*env)->NewStringUTF (env, _value);
- g_free ((gpointer) _value);
-
- return result;
-} /* Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1get_1string */
+ const char *_key = NULL;
+ const char *_value = NULL;
+ GError *err = NULL;
+ jstring result = NULL;
+
+ _key = JCL_jstring_to_cstring (env, key);
+ if (_key == NULL)
+ {
+ return NULL;
+ }
+
+ gdk_threads_enter ();
+ _value = gconf_client_get_string (client, _key, &err);
+ gdk_threads_leave ();
+ JCL_free_cstring (env, key, _key);
+ if (err != NULL)
+ {
+ /* just in case */
+ if (_value != NULL) g_free ((gpointer) _value);
+ g_error_free (err);
+ err = NULL;
+
+ return NULL;
+ }
+
+ /* Even if Gconf reported no error it is possible that NULL was returned */
+ /* and it should be prevented to create a Java string from that value. */
+ if (_value != NULL)
+ {
+ result = (*env)->NewStringUTF (env, _value);
+ g_free ((gpointer) _value);
+ }
+
+ return result;
+}
/*
* Class: gnu_java_util_prefs_gconf_GConfNativePeer
@@ -345,28 +399,38 @@ Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1get_1string
*/
JNIEXPORT jboolean JNICALL
Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1set_1string
- (JNIEnv *env, jclass clazz __attribute__ ((unused)),
- jstring key, jstring value)
+ (JNIEnv *env, jclass clazz __attribute__ ((unused)),
+ jstring key, jstring value)
{
- const char *_key = NULL;
- const char *_value = NULL;
-
- gboolean result = JNI_FALSE;
-
- /* load an UTF string from the virtual machine. */
- _key = JCL_jstring_to_cstring (env, key);
- _value = JCL_jstring_to_cstring (env, value);
- if (_key == NULL && _value == NULL) {
- return JNI_FALSE;
- }
-
- result = gconf_client_set_string (client, _key, _value, NULL);
-
- JCL_free_cstring (env, key, _key);
- JCL_free_cstring (env, value, _value);
-
- return (jboolean) result;
-} /* Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1set_1string */
+ const char *_key = NULL;
+ const char *_value = NULL;
+ GError *err = NULL;
+
+ gboolean result = JNI_FALSE;
+
+ /* load an UTF string from the virtual machine. */
+ _key = JCL_jstring_to_cstring (env, key);
+ _value = JCL_jstring_to_cstring (env, value);
+ if (_key == NULL || _value == NULL)
+ {
+ return JNI_FALSE;
+ }
+
+ gdk_threads_enter ();
+ result = gconf_client_set_string (client, _key, _value, &err);
+ gdk_threads_leave ();
+ if (err != NULL)
+ {
+ g_error_free (err);
+ err = NULL;
+ result = JNI_FALSE;
+ }
+
+ JCL_free_cstring (env, key, _key);
+ JCL_free_cstring (env, value, _value);
+
+ return (jboolean) result;
+}
/*
* Class: gnu_java_util_prefs_gconf_GConfNativePeer
@@ -375,18 +439,20 @@ Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1set_1string
*/
JNIEXPORT void JNICALL
Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1remove_1dir
- (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring node)
+ (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring node)
{
- const char *dir = NULL;
-
- dir = JCL_jstring_to_cstring (env, node);
- if (dir == NULL)
- return;
-
- gconf_client_remove_dir (client, dir, NULL);
-
- JCL_free_cstring (env, node, dir);
-} /* Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1remove_1dir */
+ const char *dir = NULL;
+
+ dir = JCL_jstring_to_cstring (env, node);
+ if (dir == NULL)
+ return;
+
+ gdk_threads_enter ();
+ gconf_client_remove_dir (client, dir, NULL);
+ gdk_threads_leave ();
+
+ JCL_free_cstring (env, node, dir);
+}
/*
* Class: gnu_java_util_prefs_gconf_GConfNativePeer
@@ -395,19 +461,21 @@ Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1remove_1dir
*/
JNIEXPORT void JNICALL
Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1add_1dir
- (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring node)
+ (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring node)
{
- const char *dir = NULL;
+ const char *dir = NULL;
- dir = JCL_jstring_to_cstring (env, node);
- if (dir == NULL)
- return;
-
- /* ignore errors */
- gconf_client_add_dir (client, dir, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ dir = JCL_jstring_to_cstring (env, node);
+ if (dir == NULL)
+ return;
+
+ /* ignore errors */
+ gdk_threads_enter ();
+ gconf_client_add_dir (client, dir, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ gdk_threads_leave ();
- JCL_free_cstring (env, node, dir);
-} /* Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1add_1dir */
+ JCL_free_cstring (env, node, dir);
+}
/*
* Class: gnu_java_util_prefs_gconf_GConfNativePeer
@@ -416,22 +484,27 @@ Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1add_1dir
*/
JNIEXPORT jboolean JNICALL
Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1dir_1exists
- (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring node)
-{
- const char *dir = NULL;
- jboolean value = JNI_FALSE;
-
- dir = JCL_jstring_to_cstring (env, node);
- if (dir == NULL)
- return value;
-
- /* we ignore errors here */
- value = gconf_client_dir_exists (client, dir, NULL);
-
- JCL_free_cstring (env, node, dir);
+ (JNIEnv *env, jclass clazz __attribute__ ((unused)), jstring node)
+{
+ const char *dir = NULL;
+ GError *err = NULL;
+ jboolean value = JNI_FALSE;
+ dir = JCL_jstring_to_cstring (env, node);
+ if (dir == NULL)
return value;
-} /* Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1dir_1exists */
+
+ /* on error return false */
+ gdk_threads_enter ();
+ value = gconf_client_dir_exists (client, dir, &err);
+ gdk_threads_leave ();
+ if (err != NULL)
+ value = JNI_FALSE;
+
+ JCL_free_cstring (env, node, dir);
+
+ return value;
+}
/*
* Class: gnu_java_util_prefs_gconf_GConfNativePeer
@@ -440,23 +513,26 @@ Java_gnu_java_util_prefs_gconf_GConfNativePeer_gconf_1client_1dir_1exists
*/
JNIEXPORT void
JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_finalize_1class
- (JNIEnv *env, jclass clazz __attribute__ ((unused)))
+ (JNIEnv *env, jclass clazz __attribute__ ((unused)))
{
- if (reference_count == 0) {
- /* last reference, free all resources and return */
- g_object_unref (G_OBJECT (client));
-
- (*env)->DeleteGlobalRef (env, jlist_class);
-
- jlist_class = NULL;
- jlist_init_id = NULL;
- jlist_add_id = NULL;
-
- return;
- }
-
- reference_count--;
-} /* Java_gnu_java_util_prefs_gconf_GConfNativePeer_finalize_1class */
+ if (reference_count == 0)
+ {
+ /* last reference, free all resources and return */
+ gdk_threads_enter ();
+ g_object_unref (G_OBJECT (client));
+ gdk_threads_leave ();
+
+ (*env)->DeleteGlobalRef (env, jlist_class);
+
+ jlist_class = NULL;
+ jlist_init_id = NULL;
+ jlist_add_id = NULL;
+
+ return;
+ }
+
+ reference_count--;
+}
/* ***** END: NATIVE FUNCTIONS ***** */
@@ -464,55 +540,59 @@ JNICALL Java_gnu_java_util_prefs_gconf_GConfNativePeer_finalize_1class
static void throw_exception (JNIEnv *env, const char *msg)
{
- throw_exception_by_name (env, "java/lang/RuntimeException", msg);
-} /* throw_exception */
+ throw_exception_by_name (env, "java/lang/RuntimeException", msg);
+}
static void
throw_exception_by_name (JNIEnv *env, const char *name, const char *msg)
-{
- JCL_ThrowException(env, name, msg);
-} /* throw_exception */
+{
+ JCL_ThrowException (env, name, msg);
+}
static void init_gconf_client (void)
-{
- client = gconf_client_get_default ();
- g_type_init();
-} /* init_gconf_client */
+{
+ g_type_init ();
+ client = gconf_client_get_default ();
+}
static gboolean set_jlist_class (JNIEnv *env)
{
- jclass local_jlist_class = NULL;
-
- /* gets a reference to the ArrayList class */
- local_jlist_class = JCL_FindClass (env, "java/util/ArrayList");
- if (local_jlist_class == NULL) {
- return FALSE;
- }
-
- jlist_class = (*env)->NewGlobalRef(env, local_jlist_class);
- (*env)->DeleteLocalRef(env, local_jlist_class);
- if (jlist_class == NULL) {
- return FALSE;
- }
-
- /* and initialize it */
- jlist_init_id = (*env)->GetMethodID (env, jlist_class, "<init>", "()V");
- if (jlist_init_id == NULL) {
- return FALSE;
- }
-
- jlist_add_id = (*env)->GetMethodID (env, jlist_class, "add",
- "(Ljava/lang/Object;)Z");
- if (jlist_add_id == NULL) {
- return FALSE;
- }
-
- return TRUE;
-} /* set_jlist_class */
+ jclass local_jlist_class = NULL;
+
+ /* gets a reference to the ArrayList class */
+ local_jlist_class = JCL_FindClass (env, "java/util/ArrayList");
+ if (local_jlist_class == NULL)
+ {
+ return FALSE;
+ }
+
+ jlist_class = (*env)->NewGlobalRef (env, local_jlist_class);
+ (*env)->DeleteLocalRef (env, local_jlist_class);
+ if (jlist_class == NULL)
+ {
+ return FALSE;
+ }
+
+ /* and initialize it */
+ jlist_init_id = (*env)->GetMethodID (env, jlist_class, "<init>", "()V");
+ if (jlist_init_id == NULL)
+ {
+ return FALSE;
+ }
+
+ jlist_add_id = (*env)->GetMethodID (env, jlist_class, "add",
+ "(Ljava/lang/Object;)Z");
+ if (jlist_add_id == NULL)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
static jobject get_jlist_reference (JNIEnv *env, jclass jlist_class)
{
- return (*env)->NewObject(env, jlist_class, jlist_init_id);
-} /* get_jlist_reference */
+ return (*env)->NewObject (env, jlist_class, jlist_init_id);
+}
/* ***** END: PRIVATE FUNCTIONS IMPLEMENTATION ***** */
diff --git a/native/jni/gconf-peer/Makefile.am b/native/jni/gconf-peer/Makefile.am
index 4c728fd8c..d88218326 100644
--- a/native/jni/gconf-peer/Makefile.am
+++ b/native/jni/gconf-peer/Makefile.am
@@ -5,10 +5,8 @@ libgconfpeer_la_SOURCES = GConfNativePeer.c
libgconfpeer_la_LIBADD = $(top_builddir)/native/jni/classpath/native_state.lo \
$(top_builddir)/native/jni/classpath/jcl.lo
-AM_LDFLAGS = @CLASSPATH_MODULE@ @GCONF_LIBS@
-#@CLASSPATH_MODULE@ @GCONF_LIBS@ @CAIRO_LIBS@ @FREETYPE2_LIBS@ \
-# @PANGOFT2_LIBS@ @X_PRE_LIBS@ @X_LIBS@ @X_EXTRA_LIBS@ -lX11 -lXtst
+AM_LDFLAGS = @CLASSPATH_MODULE@ @GCONF_LIBS@ @GDK_LIBS@
AM_CPPFLAGS = @CLASSPATH_INCLUDES@
-AM_CFLAGS = @WARNING_CFLAGS@ @ERROR_CFLAGS@ @GCONF_CFLAGS@
+AM_CFLAGS = @WARNING_CFLAGS@ @ERROR_CFLAGS@ @GCONF_CFLAGS@ @GDK_CFLAGS@
diff --git a/native/jni/gtk-peer/GtkDragSourceContextPeer.c b/native/jni/gtk-peer/GtkDragSourceContextPeer.c
new file mode 100644
index 000000000..62ffa1395
--- /dev/null
+++ b/native/jni/gtk-peer/GtkDragSourceContextPeer.c
@@ -0,0 +1,330 @@
+/* gtkdragsourcecontextpeer.c -- Native implementation of GtkDragSourceContextPeer
+ 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. */
+
+#include "gtkpeer.h"
+#include "GtkDragSourceContextPeer.h"
+
+#include <jni.h>
+#include <gtk/gtk.h>
+
+static GtkWidget * get_widget (GtkWidget *widget);
+static void connect_signals_for_widget (GtkWidget *widget);
+
+#define ACTION_COPY 1
+#define ACTION_MOVE 2
+#define ACTION_COPY_OR_MOVE 3
+#define ACTION_LINK 1073741824
+
+#define AWT_DEFAULT_CURSOR 0
+#define AWT_CROSSHAIR_CURSOR 1
+#define AWT_TEXT_CURSOR 2
+#define AWT_WAIT_CURSOR 3
+#define AWT_SW_RESIZE_CURSOR 4
+#define AWT_SE_RESIZE_CURSOR 5
+#define AWT_NW_RESIZE_CURSOR 6
+#define AWT_NE_RESIZE_CURSOR 7
+#define AWT_N_RESIZE_CURSOR 8
+#define AWT_S_RESIZE_CURSOR 9
+#define AWT_W_RESIZE_CURSOR 10
+#define AWT_E_RESIZE_CURSOR 11
+#define AWT_HAND_CURSOR 12
+#define AWT_MOVE_CURSOR 13
+
+static jmethodID dragEnterID;
+static jmethodID dragExitID;
+static jmethodID dragDropEndID;
+static jmethodID dragMouseMovedID;
+static jmethodID dragOverID;
+static jmethodID dragActionChangedID;
+static jmethodID acceptDragID;
+static jmethodID rejectDragID;
+static jmethodID acceptDropID;
+static jmethodID rejectDropID;
+static jmethodID dropCompleteID;
+
+GtkWidget *widget;
+GtkWidget *tgt;
+jobject *gref;
+jobject javaObj;
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_create
+ (JNIEnv *env, jobject obj, jobject comp)
+{
+ gdk_threads_enter ();
+
+ javaObj = obj;
+ NSA_SET_GLOBAL_REF (env, obj);
+ NSA_SET_GLOBAL_REF (env, comp);
+
+ gref = NSA_GET_PTR (env, comp);
+ widget = get_widget (GTK_WIDGET (gref));
+
+ gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_nativeSetCursor
+ (JNIEnv *env, jobject obj, jint type)
+{
+ void *ptr;
+ GdkWindow *win;
+ GdkCursorType gdk_cursor_type;
+ GdkCursor *gdk_cursor;
+
+ gdk_threads_enter ();
+
+ javaObj = obj;
+ ptr = NSA_GET_GLOBAL_REF (env, obj);
+
+ switch (type)
+ {
+ case AWT_CROSSHAIR_CURSOR:
+ gdk_cursor_type = GDK_CROSSHAIR;
+ break;
+ case AWT_TEXT_CURSOR:
+ gdk_cursor_type = GDK_XTERM;
+ break;
+ case AWT_WAIT_CURSOR:
+ gdk_cursor_type = GDK_WATCH;
+ break;
+ case AWT_SW_RESIZE_CURSOR:
+ gdk_cursor_type = GDK_BOTTOM_LEFT_CORNER;
+ break;
+ case AWT_SE_RESIZE_CURSOR:
+ gdk_cursor_type = GDK_BOTTOM_RIGHT_CORNER;
+ break;
+ case AWT_NW_RESIZE_CURSOR:
+ gdk_cursor_type = GDK_TOP_LEFT_CORNER;
+ break;
+ case AWT_NE_RESIZE_CURSOR:
+ gdk_cursor_type = GDK_TOP_RIGHT_CORNER;
+ break;
+ case AWT_N_RESIZE_CURSOR:
+ gdk_cursor_type = GDK_TOP_SIDE;
+ break;
+ case AWT_S_RESIZE_CURSOR:
+ gdk_cursor_type = GDK_BOTTOM_SIDE;
+ break;
+ case AWT_W_RESIZE_CURSOR:
+ gdk_cursor_type = GDK_LEFT_SIDE;
+ break;
+ case AWT_E_RESIZE_CURSOR:
+ gdk_cursor_type = GDK_RIGHT_SIDE;
+ break;
+ case AWT_HAND_CURSOR:
+ gdk_cursor_type = GDK_HAND2;
+ break;
+ case AWT_MOVE_CURSOR:
+ gdk_cursor_type = GDK_FLEUR;
+ break;
+ default:
+ gdk_cursor_type = GDK_LEFT_PTR;
+ }
+
+ win = widget->window;
+ if ((widget->window) == NULL)
+ win = widget->window;
+
+ gdk_cursor = gdk_cursor_new (gdk_cursor_type);
+
+ gdk_window_set_cursor (win, gdk_cursor);
+ gdk_cursor_unref (gdk_cursor);
+
+ gdk_flush();
+
+ gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_connectSignals
+ (JNIEnv *env, jobject obj, jobject comp)
+{
+ jclass gtkdragsourcecontextpeer;
+ jclass gtkdroptargetcontextpeer;
+
+ gdk_threads_enter ();
+
+ javaObj = obj;
+ gref = NSA_GET_GLOBAL_REF (env, comp);
+
+ connect_signals_for_widget (widget);
+
+ gtkdragsourcecontextpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(),
+ "gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer");
+
+ dragEnterID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(),
+ gtkdragsourcecontextpeer,
+ "dragEnter", "(II)V");
+ dragExitID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(),
+ gtkdragsourcecontextpeer,
+ "dragExit", "(III)V");
+ dragDropEndID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(),
+ gtkdragsourcecontextpeer,
+ "dragDropEnd", "(IZII)V");
+ dragMouseMovedID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(),
+ gtkdragsourcecontextpeer,
+ "dragMouseMoved", "(II)V");
+ dragOverID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(),
+ gtkdragsourcecontextpeer,
+ "dragOver", "(II)V");
+ dragActionChangedID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(),
+ gtkdragsourcecontextpeer,
+ "dragActionChanged", "(II)V");
+
+
+ gtkdroptargetcontextpeer = (*cp_gtk_gdk_env())->FindClass (cp_gtk_gdk_env(),
+ "gnu/java/awt/dnd/peer/gtk/GtkDropTargetContextPeer");
+
+ acceptDragID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(),
+ gtkdroptargetcontextpeer,
+ "acceptDrag", "(I)V");
+ rejectDragID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(),
+ gtkdroptargetcontextpeer,
+ "rejectDrag", "()V");
+ acceptDropID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(),
+ gtkdroptargetcontextpeer,
+ "acceptDrop", "(I)V");
+ rejectDropID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(),
+ gtkdroptargetcontextpeer,
+ "rejectDrop", "()V");
+ dropCompleteID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(),
+ gtkdroptargetcontextpeer,
+ "dropComplete", "(Z)V");
+
+ gdk_threads_leave ();
+}
+
+static void
+connect_signals_for_widget (GtkWidget *w)
+{
+ /* FIXME: Not implemented. */
+ w = NULL;
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_setTarget
+ (JNIEnv *env, jobject obj, jobject target)
+{
+ void *ptr;
+
+ gdk_threads_enter ();
+
+ javaObj = obj;
+ ptr = NSA_GET_PTR (env, target);
+ tgt = get_widget (GTK_WIDGET (ptr));
+ connect_signals_for_widget (tgt);
+
+ gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_nativeStartDrag
+ (JNIEnv *env, jobject obj, jobject img, jint x, jint y, jint act,
+ jstring target)
+{
+ void *ptr;
+ const gchar *data;
+ GtkTargetEntry tar[1];
+ GdkEvent *event;
+ GdkPixbuf *image = NULL;
+ GdkDragContext *context = NULL;
+ GdkDragAction action = GDK_ACTION_DEFAULT;
+
+ gdk_threads_enter ();
+
+ javaObj = obj;
+ ptr = NSA_GET_GLOBAL_REF (env, obj);
+
+ data = (*env)->GetStringUTFChars (env, target, NULL);
+ tar[0].target = (gchar *) data;
+ event = gdk_event_new (GDK_ALL_EVENTS_MASK);
+
+ switch (act)
+ {
+ case ACTION_COPY:
+ action = GDK_ACTION_COPY;
+ break;
+ case ACTION_MOVE:
+ action = GDK_ACTION_MOVE;
+ break;
+ case ACTION_COPY_OR_MOVE:
+ action = GDK_ACTION_COPY | GDK_ACTION_MOVE;
+ break;
+ case ACTION_LINK:
+ action = GDK_ACTION_LINK;
+ break;
+ default:
+ action = GDK_ACTION_DEFAULT;
+ }
+
+ gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_ALL, tar,
+ sizeof (tar) / sizeof (GtkTargetEntry),
+ action);
+ context = gtk_drag_begin (widget,
+ gtk_target_list_new (tar, sizeof (tar) / sizeof (GtkTargetEntry)),
+ action, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK, event);
+
+ if (img != NULL)
+ {
+ image = cp_gtk_image_get_pixbuf (env, img);
+ gtk_drag_set_icon_pixbuf (context, image, x, y);
+ }
+
+ if (tgt != NULL)
+ gtk_drag_dest_set (tgt, GTK_DEST_DEFAULT_ALL, tar,
+ sizeof (tar) / sizeof (GtkTargetEntry),
+ action);
+
+ gdk_event_free (event);
+ (*env)->ReleaseStringUTFChars (env, target, data);
+
+ gdk_threads_leave ();
+}
+
+static GtkWidget *
+get_widget (GtkWidget *widget)
+{
+ GtkWidget *w;
+
+ if (GTK_IS_EVENT_BOX (widget) || GTK_IS_CONTAINER (widget))
+ w = gtk_bin_get_child (GTK_BIN(widget));
+ else
+ w = widget;
+
+ return w;
+}
diff --git a/native/jni/gtk-peer/Makefile.am b/native/jni/gtk-peer/Makefile.am
index 397240270..b7e84144e 100644
--- a/native/jni/gtk-peer/Makefile.am
+++ b/native/jni/gtk-peer/Makefile.am
@@ -12,7 +12,6 @@ libgtkpeer_la_SOURCES = gnu_java_awt_peer_gtk_CairoSurface.c \
gnu_java_awt_peer_gtk_GdkPixbufDecoder.c \
gnu_java_awt_peer_gtk_GdkRobotPeer.c \
gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice.c \
- gnu_java_awt_peer_gtk_GdkTextLayout.c \
gnu_java_awt_peer_gtk_GtkButtonPeer.c \
gnu_java_awt_peer_gtk_GtkCanvasPeer.c \
gnu_java_awt_peer_gtk_GtkCheckboxMenuItemPeer.c \
@@ -41,6 +40,7 @@ libgtkpeer_la_SOURCES = gnu_java_awt_peer_gtk_CairoSurface.c \
gnu_java_awt_peer_gtk_GtkToolkit.c \
gnu_java_awt_peer_gtk_GtkWindowPeer.c \
gnu_java_awt_peer_gtk_GtkVolatileImage.c \
+ GtkDragSourceContextPeer.c \
cairographics2d.h \
gthread-jni.c \
gdkdisplay.h \
@@ -51,6 +51,7 @@ libgtkpeer_la_SOURCES = gnu_java_awt_peer_gtk_CairoSurface.c \
libgtkpeer_la_LIBADD = $(top_builddir)/native/jni/classpath/native_state.lo \
$(top_builddir)/native/jni/classpath/jcl.lo
+libgtkpeer_la_LDFLAGS = -avoid-version
AM_LDFLAGS = @CLASSPATH_MODULE@ @GTK_LIBS@ @FREETYPE2_LIBS@ \
@PANGOFT2_LIBS@ @X_PRE_LIBS@ @X_LIBS@ @X_EXTRA_LIBS@ @XTEST_LIBS@
diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c
index 0057c3b8d..45cf4fbda 100644
--- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c
+++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c
@@ -239,7 +239,6 @@ Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetMatrix
{
jdouble *native_matrix = NULL;
struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer);
- g_assert (obj != NULL);
g_assert (gr != NULL);
native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL);
@@ -263,8 +262,19 @@ Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetMatrix
}
JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoScale
+(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
+ jlong pointer, jdouble x, jdouble y)
+{
+ struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer);
+ g_assert (gr != NULL);
+
+ cairo_scale (gr->cr, x, y);
+}
+
+JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoDrawGlyphVector
-(JNIEnv *env, jobject obj, jlong pointer,
+(JNIEnv *env, jobject obj __attribute__((unused)), jlong pointer,
jobject font,
jfloat x, jfloat y, jint n,
jintArray java_codes,
@@ -278,7 +288,6 @@ Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoDrawGlyphVector
float *native_positions;
jint i = 0;
- g_assert (obj != NULL);
g_assert (java_codes != NULL);
g_assert (java_positions != NULL);
@@ -306,7 +315,9 @@ Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoDrawGlyphVector
(*env)->ReleaseFloatArrayElements (env, java_positions, native_positions, 0);
(*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0);
+ pango_fc_font_lock_face( (PangoFcFont *)pfont->font );
cairo_show_glyphs (gr->cr, glyphs, n);
+ pango_fc_font_unlock_face( (PangoFcFont *)pfont->font );
g_free(glyphs);
}
@@ -473,6 +484,28 @@ Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSetDash
}
JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoSave
+(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
+ jlong pointer)
+{
+ struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer);
+ g_assert (gr != NULL);
+
+ cairo_save (gr->cr);
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRestore
+(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
+ jlong pointer)
+{
+ struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer);
+ g_assert (gr != NULL);
+
+ cairo_restore (gr->cr);
+}
+
+JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoNewPath
(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
jlong pointer)
@@ -561,6 +594,17 @@ Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoRectangle
}
JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoArc
+(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
+ jlong pointer, jdouble x, jdouble y, jdouble radius, jdouble angle1,
+ jdouble angle2)
+{
+ struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, pointer);
+
+ cairo_arc (gr->cr, x, y, radius, angle1, angle2);
+}
+
+JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_CairoGraphics2D_cairoClosePath
(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
jlong pointer)
@@ -719,18 +763,19 @@ install_font_peer(cairo_t *cr,
if (pfont->graphics_resource == NULL)
{
- face = pango_ft2_font_get_face (pfont->font);
+ face = pango_fc_font_lock_face( (PangoFcFont *)pfont->font );
g_assert (face != NULL);
ft = cairo_ft_font_face_create_for_ft_face (face, 0);
g_assert (ft != NULL);
cairo_set_font_face (cr, ft);
- cairo_font_face_destroy (ft);
+ /* cairo_font_face_destroy (ft);*/
cairo_set_font_size (cr,
(pango_font_description_get_size (pfont->desc) /
(double)PANGO_SCALE));
ft = cairo_get_font_face (cr);
+ pango_fc_font_unlock_face( (PangoFcFont *)pfont->font );
pfont->graphics_resource = ft;
}
else
diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c
index 5927b21fa..25163cd9f 100644
--- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c
+++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c
@@ -276,6 +276,42 @@ Java_gnu_java_awt_peer_gtk_ComponentGraphics_copyAreaNative
gdk_threads_leave();
}
+JNIEXPORT jobject JNICALL
+Java_gnu_java_awt_peer_gtk_ComponentGraphics_nativeGrab
+(JNIEnv *env, jclass cls __attribute__((unused)), jobject peer )
+{
+ GdkPixbuf *pixbuf;
+ GdkDrawable *drawable;
+ GdkWindow *win;
+ gint w,h;
+ GtkWidget *widget = NULL;
+ void *ptr = NULL;
+
+ gdk_threads_enter();
+
+ ptr = NSA_GET_PTR (env, peer);
+ g_assert (ptr != NULL);
+
+ widget = GTK_WIDGET (ptr);
+ g_assert (widget != NULL);
+
+ cp_gtk_grab_current_drawable (widget, &drawable, &win);
+ g_assert (drawable != NULL);
+
+ gdk_drawable_get_size ( drawable, &w, &h );
+
+ pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, TRUE, 8, w, h );
+ gdk_pixbuf_get_from_drawable( pixbuf, drawable, NULL, 0, 0, 0, 0, w, h );
+ g_object_ref( pixbuf );
+ gdk_draw_pixbuf (drawable, NULL, pixbuf,
+ 0, 0, 0, 0,
+ w, h,
+ GDK_RGB_DITHER_NORMAL, 0, 0);
+ gdk_threads_leave();
+
+ return JCL_NewRawDataObject (env, pixbuf);
+}
+
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_ComponentGraphics_drawVolatile
(JNIEnv *env, jobject obj __attribute__ ((unused)), jobject peer,
diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c
index 89adcd1e5..6528ad43a 100644
--- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c
+++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c
@@ -241,3 +241,35 @@ Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_nativeGetDefaultScreenDevice
return defaultDevice;
}
+
+JNIEXPORT jintArray JNICALL
+Java_gnu_java_awt_peer_gtk_GdkGraphicsEnvironment_getMouseCoordinates
+(JNIEnv *env, jobject obj)
+{
+ jintArray retArray;
+ jint *values;
+ GdkDisplay *display;
+ gint x, y, screenIndex;
+ GdkScreen *screen;
+
+ display = (GdkDisplay *) NSA_GET_DISPLAY_PTR(env, obj);
+ g_assert (display != NULL);
+
+ gdk_threads_enter ();
+
+ gdk_display_get_pointer (display, &screen, &x, &y, NULL);
+ screenIndex = gdk_screen_get_number( screen );
+
+ gdk_threads_leave ();
+
+ retArray = (*env)->NewIntArray (env, 3);
+ values = (*env)->GetIntArrayElements (env, retArray, NULL);
+
+ values[0] = screenIndex;
+ values[1] = x;
+ values[2] = y;
+
+ (*env)->ReleaseIntArrayElements (env, retArray, values, 0);
+
+ return retArray;
+}
diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice.c
index 965fb5a23..4053ad8b6 100644
--- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice.c
+++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice.c
@@ -248,8 +248,8 @@ Java_gnu_java_awt_peer_gtk_GdkScreenGraphicsDevice_nativeGetDisplayModes
/* Retrieves refresh rate information. */
rates = XRRConfigRates(config, i, &nrates);
- /* Create a Java int array and put them in. */
- shortArray = (*env)->NewIntArray(env, nrates);
+ /* Create a Java short array and put them in. */
+ shortArray = (*env)->NewShortArray(env, nrates);
(*env)->SetShortArrayRegion(env, shortArray, 0, nrates, (jshort *) rates);
/* Create a GdkScreenGraphicsDevice.X11DisplayMode instance. */
diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c
deleted file mode 100644
index 849998791..000000000
--- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/* gnu_java_awt_GdkTextLayout.c
- Copyright (C) 2004, 2005, 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. */
-
-
-#include <jni.h>
-#include <gtk/gtk.h>
-#include <string.h>
-#include <pango/pango.h>
-#include <pango/pangoft2.h>
-#include <pango/pangofc-font.h>
-#include <freetype/ftglyph.h>
-#include <freetype/ftoutln.h>
-#include "jcl.h"
-#include "native_state.h"
-#include "gdkfont.h"
-#include "gnu_java_awt_peer_gtk_GdkTextLayout.h"
-#include "cairographics2d.h"
-
-struct state_table *cp_gtk_native_text_layout_state_table;
-
-typedef struct gp
-{
- JNIEnv *env;
- jobject obj;
- double px;
- double py;
- double sx;
- double sy;
-} generalpath ;
-
-static void paint_glyph_run(cairo_t *cr, cairo_glyph_t **glyphs,
- gint *n_glyphs, PangoLayoutRun *run);
-
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GdkTextLayout_initStaticState
- (JNIEnv *env, jclass clazz)
-{
- NSA_TEXT_LAYOUT_INIT (env, clazz);
-}
-
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GdkTextLayout_initState
- (JNIEnv *env, jobject self)
-{
- struct textlayout *tl;
-
- gdk_threads_enter ();
-
- g_assert(self != NULL);
- tl = g_malloc0 (sizeof (struct textlayout));
- g_assert(tl != NULL);
- tl->pango_layout = pango_layout_new(gdk_pango_context_get());
- g_assert(tl->pango_layout != NULL);
- NSA_SET_TEXT_LAYOUT_PTR (env, self, tl);
-
- gdk_threads_leave ();
-}
-
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GdkTextLayout_setText
- (JNIEnv *env, jobject self, jstring text)
-{
- struct textlayout *tl;
- gchar *str = NULL;
- gint len = 0;
-
- g_assert(self != NULL);
- g_assert(text != NULL);
-
- tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, self);
- g_assert(tl != NULL);
- g_assert(tl->pango_layout != NULL);
-
- len = (*env)->GetStringUTFLength (env, text);
- str = (gchar *)(*env)->GetStringUTFChars (env, text, NULL);
- g_assert (str != NULL);
-
- gdk_threads_enter ();
-
- pango_layout_set_text (tl->pango_layout, str, len);
-
- (*env)->ReleaseStringUTFChars (env, text, str);
-
- gdk_threads_leave ();
-}
-
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GdkTextLayout_setFont (JNIEnv *env, jobject obj, jobject font)
-{
- struct textlayout *tl;
- struct peerfont *pf;
-
- g_assert(obj != NULL);
- g_assert(font != NULL);
-
- tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, obj);
- g_assert(tl != NULL);
- g_assert(tl->pango_layout != NULL);
- pf = (struct peerfont *)NSA_GET_FONT_PTR (env, font);
- g_assert(pf != NULL);
-
- gdk_threads_enter ();
-
- pango_layout_set_font_description(tl->pango_layout, pf->desc);
-
- gdk_threads_leave ();
-}
-
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GdkTextLayout_indexToPos
- (JNIEnv *env, jobject self, jint idx, jdoubleArray javaPos)
-{
- struct textlayout *tl;
- PangoRectangle pangoPos;
- jdouble *nativePos;
-
- gdk_threads_enter ();
-
- g_assert(self != NULL);
- g_assert(javaPos != NULL);
-
- tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, self);
- g_assert(tl != NULL);
- g_assert(tl->pango_layout != NULL);
-
- g_assert((*env)->GetArrayLength (env, javaPos) == 4);
-
- nativePos = (*env)->GetDoubleArrayElements (env, javaPos, NULL);
-
- pango_layout_index_to_pos (tl->pango_layout, idx, &pangoPos);
-
- nativePos[0] = (jdouble) pangoPos.x;
- nativePos[1] = (jdouble) pangoPos.y;
- nativePos[2] = (jdouble) pangoPos.width;
- nativePos[3] = (jdouble) pangoPos.height;
-
- (*env)->ReleaseDoubleArrayElements (env, javaPos, nativePos, 0);
-
- gdk_threads_leave ();
-}
-
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GdkTextLayout_getExtents
- (JNIEnv *env, jobject self, jdoubleArray javaInkExtents, jdoubleArray javaLogExtents)
-{
- struct textlayout *tl;
- PangoRectangle pangoInkExtents, pangoLogExtents;
- jdouble *nativeInkExtents, *nativeLogExtents;
-
- gdk_threads_enter ();
-
- g_assert(self != NULL);
- g_assert(javaInkExtents != NULL);
- g_assert(javaLogExtents != NULL);
-
- tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, self);
- g_assert(tl != NULL);
- g_assert(tl->pango_layout != NULL);
-
- g_assert((*env)->GetArrayLength (env, javaInkExtents) == 4);
- g_assert((*env)->GetArrayLength (env, javaLogExtents) == 4);
-
- nativeInkExtents = (*env)->GetDoubleArrayElements (env, javaInkExtents, NULL);
- nativeLogExtents = (*env)->GetDoubleArrayElements (env, javaLogExtents, NULL);
-
- pango_layout_get_extents (tl->pango_layout,
- &pangoInkExtents, &pangoLogExtents);
-
- nativeInkExtents[0] = (jdouble) pangoInkExtents.x;
- nativeInkExtents[1] = (jdouble) pangoInkExtents.y;
- nativeInkExtents[2] = (jdouble) pangoInkExtents.width;
- nativeInkExtents[3] = (jdouble) pangoInkExtents.height;
-
- nativeLogExtents[0] = (jdouble) pangoLogExtents.x;
- nativeLogExtents[1] = (jdouble) pangoLogExtents.y;
- nativeLogExtents[2] = (jdouble) pangoLogExtents.width;
- nativeLogExtents[3] = (jdouble) pangoLogExtents.height;
-
- (*env)->ReleaseDoubleArrayElements (env, javaInkExtents, nativeInkExtents, 0);
- (*env)->ReleaseDoubleArrayElements (env, javaLogExtents, nativeLogExtents, 0);
-
- gdk_threads_leave ();
-}
-
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GdkTextLayout_dispose
- (JNIEnv *env, jobject self)
-{
- struct textlayout *tl;
-
- gdk_threads_enter ();
-
- g_assert(self != NULL);
- tl = (struct textlayout *) NSA_DEL_TEXT_LAYOUT_PTR (env, self);
- g_assert(tl != NULL);
- if (tl->pango_layout != NULL)
- g_object_unref (tl->pango_layout);
- g_free(tl);
-
- gdk_threads_leave ();
-}
-
-/**
- * Draw this textlayout on a cairo surface
- * FIXME: Seems completely broken.
- */
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GdkTextLayout_cairoDrawGdkTextLayout
- (JNIEnv *env, jobject obj, jlong cg2d, jfloat x, jfloat y)
-{
- /*
- * FIXME: Some day we expect either cairo or pango will know how to make
- * a pango layout paint to a cairo surface. that day is not yet here.
- */
-
- struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, cg2d);
- cairo_t *cr = gr->cr;
- struct textlayout *tl = NULL;
- PangoLayoutIter *i = NULL;
- PangoLayoutRun *run = NULL;
- cairo_glyph_t *glyphs = NULL;
- gint n_glyphs = 0;
-
- tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, obj);
-
- g_assert (cr != NULL);
- g_assert (tl != NULL);
- g_assert (tl->pango_layout != NULL);
-
- gdk_threads_enter ();
-
- i = pango_layout_get_iter (tl->pango_layout);
- g_assert (i != NULL);
-
- cairo_translate (cr, x, y);
-
- do
- {
- run = pango_layout_iter_get_run (i);
- if (run != NULL)
- paint_glyph_run (cr, &glyphs, &n_glyphs, run);
- }
- while (pango_layout_iter_next_run (i));
-
- if (glyphs != NULL)
- g_free (glyphs);
-
- cairo_translate (cr, -x, -y);
-
- pango_layout_iter_free (i);
-
- gdk_threads_leave ();
-}
-
-static void
-paint_glyph_run(cairo_t *cr,
- cairo_glyph_t **glyphs,
- gint *n_glyphs,
- PangoLayoutRun *run)
-{
- gint i = 0;
- gint x = 0, y = 0;
-
- g_assert (cr != NULL);
- g_assert (glyphs != NULL);
- g_assert (n_glyphs != NULL);
- g_assert (run != NULL);
-
- if (run->glyphs != NULL && run->glyphs->num_glyphs > 0)
- {
- if (*n_glyphs < run->glyphs->num_glyphs)
- {
- *glyphs = g_realloc(*glyphs,
- (sizeof(cairo_glyph_t)
- * run->glyphs->num_glyphs));
- *n_glyphs = run->glyphs->num_glyphs;
- }
-
- g_assert (*glyphs != NULL);
-
- for (i = 0; i < run->glyphs->num_glyphs; ++i)
- {
- (*glyphs)[i].index = run->glyphs->glyphs[i].glyph;
-
- (*glyphs)[i].x =
- ((double) (x + run->glyphs->glyphs[i].geometry.x_offset))
- / ((double) PANGO_SCALE);
-
- (*glyphs)[i].y =
- ((double) (y + run->glyphs->glyphs[i].geometry.y_offset))
- / ((double) PANGO_SCALE);
-
- x += run->glyphs->glyphs[i].geometry.width;
- }
- cairo_show_glyphs (cr, *glyphs, run->glyphs->num_glyphs);
- }
-}
-
-/* GetOutline code follows ****************************/
-/********* Freetype callback functions *****************************/
-
-static int _moveTo( const FT_Vector* to,
- void *p)
-{
- JNIEnv *env;
- jobject obj;
- jclass cls;
- jmethodID method;
- jvalue values[2];
- generalpath *path = (generalpath *) p;
-
- env = path->env;
- obj = path->obj;
-
- values[0].f = (jfloat)(to->x * path->sx + path->px);
- values[1].f = (jfloat)(to->y * path->sy + path->py);
-
- cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
- method = (*env)->GetMethodID (env, cls, "moveTo", "(FF)V");
- (*env)->CallVoidMethodA(env, obj, method, values );
-
- return 0;
-}
-
-static int _lineTo( const FT_Vector* to,
- void *p)
-{
- JNIEnv *env;
- jobject obj;
- jclass cls;
- jmethodID method;
- jvalue values[2];
- generalpath *path = (generalpath *) p;
-
- env = path->env;
- obj = path->obj;
- values[0].f = (jfloat)(to->x * path->sx + path->px);
- values[1].f = (jfloat)(to->y * path->sy + path->py);
-
- cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
- method = (*env)->GetMethodID (env, cls, "lineTo", "(FF)V");
- (*env)->CallVoidMethodA(env, obj, method, values );
-
- return 0;
-}
-
-static int _quadTo( const FT_Vector* cp,
- const FT_Vector* to,
- void *p)
-{
- JNIEnv *env;
- jobject obj;
- jclass cls;
- jmethodID method;
- jvalue values[4];
- generalpath *path = (generalpath *) p;
-
- env = path->env;
- obj = path->obj;
- values[0].f = (jfloat)(cp->x * path->sx + path->px);
- values[1].f = (jfloat)(cp->y * path->sy + path->py);
- values[2].f = (jfloat)(to->x * path->sx + path->px);
- values[3].f = (jfloat)(to->y * path->sy + path->py);
-
- cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
- method = (*env)->GetMethodID (env, cls, "quadTo", "(FFFF)V");
- (*env)->CallVoidMethodA(env, obj, method, values );
-
- return 0;
-}
-
-static int _curveTo( const FT_Vector* cp1,
- const FT_Vector* cp2,
- const FT_Vector* to,
- void *p)
-{
- JNIEnv *env;
- jobject obj;
- jclass cls;
- jmethodID method;
- jvalue values[6];
- generalpath *path = (generalpath *) p;
-
- env = path->env;
- obj = path->obj;
- values[0].f = (jfloat)(cp1->x * path->sx + path->px);
- values[1].f = (jfloat)(cp1->y * path->sy + path->py);
- values[2].f = (jfloat)(cp2->x * path->sx + path->px);
- values[3].f = (jfloat)(cp2->y * path->sy + path->py);
- values[4].f = (jfloat)(to->x * path->sx + path->px);
- values[5].f = (jfloat)(to->y * path->sy + path->py);
-
- cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
- method = (*env)->GetMethodID (env, cls, "curveTo", "(FFFFFF)V");
- (*env)->CallVoidMethodA(env, obj, method, values );
-
- return 0;
-}
-
-
-JNIEXPORT jobject JNICALL
-Java_gnu_java_awt_peer_gtk_GdkTextLayout_getOutline
- (JNIEnv *env, jobject obj, jobject transform)
-{
- struct textlayout *tl;
- generalpath *path;
- jobject gp;
- GSList *current_run;
- PangoLayoutLine *current_line;
- FT_Outline_Funcs ftCallbacks =
- {
- (FT_Outline_MoveToFunc) _moveTo,
- (FT_Outline_LineToFunc) _lineTo,
- (FT_Outline_ConicToFunc) _quadTo,
- (FT_Outline_CubicToFunc) _curveTo,
- 0,
- 0
- };
- PangoLayoutIter* layoutIterator;
-
- gdk_threads_enter ();
-
- tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, obj);
- g_assert(tl != NULL);
- g_assert(tl->pango_layout != NULL);
-
- path = g_malloc0 (sizeof (generalpath));
- g_assert(path != NULL);
- path->env = env;
-
- /* Scaling factors */
- path->sx = PANGO_SCALE/65536.0;
- path->sy = -PANGO_SCALE/65536.0;
-
- { /* create a GeneralPath instance */
- jclass cls;
- jmethodID method;
-
- cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
- method = (*env)->GetMethodID (env, cls, "<init>", "()V");
- gp = path->obj = (*env)->NewObject (env, cls, method);
- }
-
- layoutIterator = pango_layout_get_iter (tl->pango_layout);
- g_assert (layoutIterator != NULL);
-
- if (pango_layout_iter_get_line (layoutIterator))
- do
- {
- PangoRectangle line_logical_rect;
- current_line = pango_layout_iter_get_line (layoutIterator);
- pango_layout_iter_get_line_extents (layoutIterator,
- NULL,
- &line_logical_rect);
-
- path->px = line_logical_rect.x/(double)PANGO_SCALE;
- path->py = line_logical_rect.y/(double)PANGO_SCALE;
-
- current_run = current_line->runs;
- while (current_run)
- {
- FT_Face ft_face;
- int index;
- PangoGlyphItem *run = current_run->data;
- PangoGlyphString *glyphs = run->glyphs;
-
- PangoAnalysis *analysis = &run->item->analysis;
- g_assert (analysis != NULL);
- g_assert (analysis->font != NULL);
-
- ft_face = pango_fc_font_lock_face ((PangoFcFont *)analysis->font);
- g_assert (ft_face != NULL);
-
- for (index = 0; index < glyphs->num_glyphs; index++)
- {
- FT_Glyph glyph;
- FT_Error fterror;
- PangoGlyphGeometry pgg = glyphs->glyphs[index].geometry;
-
- fterror = FT_Load_Glyph(ft_face,
- (FT_UInt)(glyphs->glyphs[index].glyph),
- FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP);
- g_assert(fterror == 0);
-
- FT_Get_Glyph (ft_face->glyph, &glyph);
- FT_Outline_Decompose (&(((FT_OutlineGlyph)glyph)->outline),
- &ftCallbacks, path);
- FT_Done_Glyph (glyph);
-
- path->px += pgg.width/(double)PANGO_SCALE;
- }
-
- pango_fc_font_unlock_face ((PangoFcFont *)analysis->font);
- current_run = current_run->next;
- }
- } while (pango_layout_iter_next_line (layoutIterator));
-
- g_free(path);
- gdk_threads_leave ();
-
- if (transform != NULL)
- {
- jclass cls;
- jmethodID method;
-
- cls = (*env)->FindClass (env, "java/awt/geom/GeneralPath");
- method = (*env)->GetMethodID (env, cls, "transform",
- "(Ljava/awt/geom/AffineTransform;)V");
- (*env)->CallVoidMethod(env, gp, method, transform );
- }
-
- return gp;
-}
diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c
index 46949d99a..ac4df69f4 100644
--- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c
+++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c
@@ -1,5 +1,5 @@
/* gtkchoicepeer.c -- Native implementation of GtkChoicePeer
- Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -52,7 +52,7 @@ cp_gtk_choice_init_jni (void)
postChoiceItemEventID = (*cp_gtk_gdk_env())->GetMethodID (cp_gtk_gdk_env(), gtkchoicepeer,
"postChoiceItemEvent",
- "(Ljava/lang/String;I)V");
+ "(I)V");
}
static void selection_changed_cb (GtkComboBox *combobox, jobject peer);
@@ -106,39 +106,7 @@ Java_gnu_java_awt_peer_gtk_GtkChoicePeer_connectSignals
}
JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkChoicePeer_append
- (JNIEnv *env, jobject obj, jobjectArray items)
-{
- gpointer ptr;
- jsize count, i;
- GtkWidget *bin;
-
- gdk_threads_enter ();
-
- ptr = NSA_GET_PTR (env, obj);
- bin = choice_get_widget (GTK_WIDGET (ptr));
-
- count = (*env)->GetArrayLength (env, items);
-
- for (i = 0; i < count; i++)
- {
- jobject item;
- const char *label;
-
- item = (*env)->GetObjectArrayElement (env, items, i);
- label = (*env)->GetStringUTFChars (env, item, NULL);
-
- gtk_combo_box_append_text (GTK_COMBO_BOX (bin), label);
-
- (*env)->ReleaseStringUTFChars (env, item, label);
- (*env)->DeleteLocalRef(env, item);
- }
-
- gdk_threads_leave ();
-}
-
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeAdd
+Java_gnu_java_awt_peer_gtk_GtkChoicePeer_add
(JNIEnv *env, jobject obj, jstring item, jint index)
{
void *ptr;
@@ -170,14 +138,16 @@ Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeRemove
ptr = NSA_GET_PTR (env, obj);
bin = choice_get_widget (GTK_WIDGET (ptr));
-
+
+ /* First, unselect everything, to avoid problems when removing items. */
+ gtk_combo_box_set_active (GTK_COMBO_BOX (bin), -1);
gtk_combo_box_remove_text (GTK_COMBO_BOX (bin), index);
gdk_threads_leave ();
}
-JNIEXPORT void JNICALL
-Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeRemoveAll
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeRemoveAll
(JNIEnv *env, jobject obj)
{
void *ptr;
@@ -224,8 +194,7 @@ Java_gnu_java_awt_peer_gtk_GtkChoicePeer_selectNativeUnlocked
ptr = NSA_GET_PTR (env, obj);
bin = choice_get_widget (GTK_WIDGET (ptr));
-
- gtk_combo_box_set_active (GTK_COMBO_BOX (bin), index);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (bin), (gint)index);
}
JNIEXPORT jint JNICALL
@@ -251,26 +220,11 @@ Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeGetSelected
static void
selection_changed_cb (GtkComboBox *combobox, jobject peer)
{
- jstring label;
- GtkTreeModel *model;
- GtkTreeIter iter;
- gchar *selected;
- gint index;
-
- index = gtk_combo_box_get_active(combobox);
+ gint index = gtk_combo_box_get_active(combobox);
if (index >= 0)
- {
- model = gtk_combo_box_get_model (combobox);
- gtk_combo_box_get_active_iter (combobox, &iter);
- gtk_tree_model_get (model, &iter, 0, &selected, -1);
- label = (*cp_gtk_gdk_env())->NewStringUTF (cp_gtk_gdk_env(), selected);
-
- (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
- postChoiceItemEventID,
- label,
- (jint) AWT_ITEM_SELECTED);
- }
+ (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), peer,
+ postChoiceItemEventID, (jint)index );
}
static GtkWidget *
diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
index 4cd80a73f..39524eea0 100644
--- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
+++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
@@ -339,6 +339,42 @@ Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetSetSensitive
gdk_threads_leave ();
}
+JNIEXPORT jboolean JNICALL
+Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetHasFocus
+(JNIEnv *env, jobject obj)
+{
+ void *ptr;
+ jboolean retval;
+
+ gdk_threads_enter ();
+
+ ptr = NSA_GET_PTR (env, obj);
+
+ retval = GTK_WIDGET_HAS_FOCUS((GTK_WIDGET (ptr)));
+
+ gdk_threads_leave ();
+
+ return retval;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetCanFocus
+(JNIEnv *env, jobject obj)
+{
+ void *ptr;
+ jboolean retval;
+
+ gdk_threads_enter ();
+
+ ptr = NSA_GET_PTR (env, obj);
+
+ retval = GTK_WIDGET_CAN_FOCUS((GTK_WIDGET (ptr)));
+
+ gdk_threads_leave ();
+
+ return retval;
+}
+
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkWidgetRequestFocus
(JNIEnv *env, jobject obj)
diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c
index c966f6331..969b7bc5c 100644
--- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c
+++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c
@@ -329,6 +329,17 @@ Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkMain
gdk_threads_leave ();
}
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkQuit
+(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)))
+{
+ gdk_threads_enter ();
+
+ gtk_main_quit ();
+
+ gdk_threads_leave ();
+}
+
static jint gdk_color_to_java_color (GdkColor color);
@@ -387,6 +398,37 @@ Java_gnu_java_awt_peer_gtk_GtkToolkit_getScreenResolution
return res;
}
+/**
+ * Report the number of mouse buttons
+ * Returns the number of buttons of the first mouse found, or -1 if no mouse
+ * seems to be connected.
+ */
+JNIEXPORT jint JNICALL
+Java_gnu_java_awt_peer_gtk_GtkToolkit_getMouseNumberOfButtons
+ (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)))
+{
+ jint res = -1;
+ GList *devices;
+ GdkDevice *d;
+
+ gdk_threads_enter ();
+
+ /* FIXME: Why doesn't this return the correct number? */
+ devices = gdk_devices_list();
+
+ while( res == -1 && devices != NULL )
+ {
+ d = GDK_DEVICE( devices->data );
+ if( d->source == GDK_SOURCE_MOUSE )
+ res = d->num_keys;
+ devices = devices->next;
+ }
+
+ gdk_threads_leave ();
+
+ return res;
+}
+
#define CONVERT(type, state) \
gdk_color_to_java_color (style->type[GTK_STATE_ ## state])
diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkVolatileImage.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkVolatileImage.c
index d7ef474e0..e391d64ec 100644
--- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkVolatileImage.c
+++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkVolatileImage.c
@@ -73,7 +73,8 @@ Java_gnu_java_awt_peer_gtk_GtkVolatileImage_init (JNIEnv *env,
pixmap = gdk_pixmap_new( widget->window, width, height, -1 );
}
else
- pixmap = gdk_pixmap_new( NULL, width, height, 16 );
+ pixmap = gdk_pixmap_new( NULL, width, height,
+ gdk_rgb_get_visual()->depth );
gdk_threads_leave();
diff --git a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
index c3ecb00c8..3f288af5c 100644
--- a/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
+++ b/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
@@ -1245,6 +1245,38 @@ Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetModal
}
JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowSetAlwaysOnTop
+ (JNIEnv *env, jobject obj, jboolean alwaysOnTop)
+{
+ void *ptr;
+
+ gdk_threads_enter ();
+
+ ptr = NSA_GET_PTR (env, obj);
+
+ gtk_window_set_keep_above (GTK_WINDOW (ptr), alwaysOnTop);
+
+ gdk_threads_leave ();
+}
+
+JNIEXPORT jboolean JNICALL
+Java_gnu_java_awt_peer_gtk_GtkWindowPeer_gtkWindowHasFocus
+(JNIEnv *env, jobject obj)
+{
+ void *ptr;
+ jboolean retval;
+
+ gdk_threads_enter ();
+
+ ptr = NSA_GET_PTR (env, obj);
+
+ retval = gtk_window_has_toplevel_focus (GTK_WINDOW (ptr));
+
+ gdk_threads_leave ();
+ return retval;
+}
+
+JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setVisibleNative
(JNIEnv *env, jobject obj, jboolean visible)
{
diff --git a/native/jni/java-lang/java_lang_VMSystem.c b/native/jni/java-lang/java_lang_VMSystem.c
index 05b0d960e..d20322791 100644
--- a/native/jni/java-lang/java_lang_VMSystem.c
+++ b/native/jni/java-lang/java_lang_VMSystem.c
@@ -113,11 +113,11 @@ Java_java_lang_VMSystem_setErr (JNIEnv * env,
/*
* Class: java_lang_VMSystem
- * Method: currentTimeMillis
+ * Method: nanoTime
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
-Java_java_lang_VMSystem_currentTimeMillis
+Java_java_lang_VMSystem_nanoTime
(JNIEnv * env __attribute__ ((__unused__)),
jclass thisClass __attribute__ ((__unused__)))
{
@@ -129,8 +129,9 @@ Java_java_lang_VMSystem_currentTimeMillis
(*env)->FatalError (env, "gettimeofday call failed.");
result = (jlong) tp.tv_sec;
- result *= 1000;
- result += (tp.tv_usec / 1000);
+ result *= (jlong)1000000L;
+ result += (jlong)tp.tv_usec;
+ result *= (jlong)1000;
return result;
}
diff --git a/native/jni/java-net/gnu_java_net_local_LocalSocketImpl.c b/native/jni/java-net/gnu_java_net_local_LocalSocketImpl.c
index 3b29001a7..35fb6bcdc 100644
--- a/native/jni/java-net/gnu_java_net_local_LocalSocketImpl.c
+++ b/native/jni/java-net/gnu_java_net_local_LocalSocketImpl.c
@@ -200,22 +200,15 @@ Java_gnu_java_net_local_LocalSocketImpl_accept (JNIEnv *env, jobject this, jobje
jint
-Java_gnu_java_net_local_LocalSocketImpl_available (JNIEnv *env, jobject this)
+Java_gnu_java_net_local_LocalSocketImpl_available
+(JNIEnv *env, jobject this __attribute__((unused)), jint fd)
{
#ifdef ENABLE_LOCAL_SOCKETS
- jfieldID socket_fd;
- jclass clazz;
jint avail;
TRACE("begin");
- clazz = (*env)->GetObjectClass (env, this);
- socket_fd = (*env)->GetFieldID (env, clazz, "socket_fd", "I");
- if (!socket_fd)
- {
- return 0;
- }
- avail = (jint) local_available ((int) (*env)->GetIntField (env, this, socket_fd));
+ avail = (jint) local_available (fd);
if (avail < 0)
{
_throw (env, "java/io/IOException", local_error ());
@@ -227,6 +220,7 @@ Java_gnu_java_net_local_LocalSocketImpl_available (JNIEnv *env, jobject this)
return avail;
#else
(void) this;
+ (void) fd;
_throw (env, "java/lang/Error", "support for local sockets not available");
return -1;
#endif /* ENABLE_LOCAL_SOCKETS */
@@ -452,14 +446,13 @@ Java_gnu_java_net_local_LocalSocketImpl_localConnect (JNIEnv *env, jobject this,
jint
-Java_gnu_java_net_local_LocalSocketImpl_read (JNIEnv *env, jobject this, jbyteArray buf, jint off, jint len)
+Java_gnu_java_net_local_LocalSocketImpl_read
+(JNIEnv *env, jobject this __attribute__((unused)), jint fd, jbyteArray buf,
+ jint off, jint len)
{
#ifdef ENABLE_LOCAL_SOCKETS
- jfieldID socket_fd;
- jclass clazz;
jbyte *buffer;
jint count;
- int fd;
TRACE("begin");
@@ -468,13 +461,6 @@ Java_gnu_java_net_local_LocalSocketImpl_read (JNIEnv *env, jobject this, jbyteAr
_throw (env, "java/lang/ArrayIndexOutOfBoundsException", "");
}
- clazz = (*env)->GetObjectClass (env, this);
- socket_fd = (*env)->GetFieldID (env, clazz, "socket_fd", "I");
- if (!socket_fd)
- {
- return 0;
- }
- fd = (int) (*env)->GetIntField (env, this, socket_fd);
buffer = (*env)->GetByteArrayElements (env, buf, NULL);
count = (jint) local_read (fd, (void *) (buffer + off), (int) len);
if (count < 0)
@@ -488,6 +474,7 @@ Java_gnu_java_net_local_LocalSocketImpl_read (JNIEnv *env, jobject this, jbyteAr
return count;
#else
(void) this;
+ (void) fd;
(void) buf;
(void) off;
(void) len;
@@ -498,13 +485,12 @@ Java_gnu_java_net_local_LocalSocketImpl_read (JNIEnv *env, jobject this, jbyteAr
void
-Java_gnu_java_net_local_LocalSocketImpl_write (JNIEnv *env, jobject this, jbyteArray buf, jint off, jint len)
+Java_gnu_java_net_local_LocalSocketImpl_write
+(JNIEnv *env, jobject this __attribute__((unused)), jint fd, jbyteArray buf,
+ jint off, jint len)
{
#ifdef ENABLE_LOCAL_SOCKETS
- jfieldID socket_fd;
- jclass clazz;
jbyte *buffer;
- int fd;
TRACE("begin");
@@ -513,13 +499,6 @@ Java_gnu_java_net_local_LocalSocketImpl_write (JNIEnv *env, jobject this, jbyteA
_throw (env, "java/lang/ArrayIndexOutOfBoundsException", "");
}
- clazz = (*env)->GetObjectClass (env, this);
- socket_fd = (*env)->GetFieldID (env, clazz, "socket_fd", "I");
- if (!socket_fd)
- {
- return;
- }
- fd = (int) (*env)->GetIntField (env, this, socket_fd);
buffer = (*env)->GetByteArrayElements (env, buf, NULL);
if (local_write (fd, (void *) (buffer + off), (int) len) < 0)
{
@@ -530,6 +509,7 @@ Java_gnu_java_net_local_LocalSocketImpl_write (JNIEnv *env, jobject this, jbyteA
TRACE("end");
#else
(void) this;
+ (void) fd;
(void) buf;
(void) off;
(void) len;
diff --git a/native/jni/java-nio/java_nio_VMDirectByteBuffer.c b/native/jni/java-nio/java_nio_VMDirectByteBuffer.c
index f725cf2a4..bfee7e9dc 100644
--- a/native/jni/java-nio/java_nio_VMDirectByteBuffer.c
+++ b/native/jni/java-nio/java_nio_VMDirectByteBuffer.c
@@ -60,6 +60,8 @@ Java_java_nio_VMDirectByteBuffer_allocate
return 0;
}
+ memset (buffer, 0, capacity);
+
return JCL_NewRawDataObject (env, buffer);
}
diff --git a/native/jni/midi-alsa/Makefile.am b/native/jni/midi-alsa/Makefile.am
index e45cb439e..4a9c48442 100644
--- a/native/jni/midi-alsa/Makefile.am
+++ b/native/jni/midi-alsa/Makefile.am
@@ -5,6 +5,7 @@ gnu_javax_sound_midi_alsa_AlsaPortDevice.c \
gnu_javax_sound_midi_alsa_AlsaMidiDeviceProvider.c
libgjsmalsa_la_LIBADD = -lasound
+libgjsmalsa_la_LDFLAGS = -avoid-version
AM_LDFLAGS = @CLASSPATH_MODULE@
AM_CPPFLAGS = @CLASSPATH_INCLUDES@ `pkg-config --cflags-only-I alsa`
diff --git a/native/jni/midi-dssi/Makefile.am b/native/jni/midi-dssi/Makefile.am
index 8a466d61f..48c8051cc 100644
--- a/native/jni/midi-dssi/Makefile.am
+++ b/native/jni/midi-dssi/Makefile.am
@@ -5,6 +5,7 @@ libgjsmdssi_la_SOURCES = gnu_javax_sound_midi_dssi_DSSIMidiDeviceProvider.c \
dssi_data.h
libgjsmdssi_la_LIBADD = $(top_builddir)/native/jni/classpath/jcl.lo -ljack
+libgjsmdssi_la_LDFLAGS = -avoid-version
AM_LDFLAGS = @CLASSPATH_MODULE@
AM_CPPFLAGS = @CLASSPATH_INCLUDES@
diff --git a/native/jni/qt-peer/Makefile.am b/native/jni/qt-peer/Makefile.am
index d39271fe7..b123ed36e 100644
--- a/native/jni/qt-peer/Makefile.am
+++ b/native/jni/qt-peer/Makefile.am
@@ -72,6 +72,7 @@ libqtpeer_la_SOURCES = \
qtwindowpeer.cpp \
slotcallbacks.cpp \
slotcallbacks.h
+libqtpeer_la_LDFLAGS = -avoid-version
BUILT_SOURCES = $(libqtpeer_la_MOC)
diff --git a/org/omg/CORBA/CompletionStatusHelper.java b/org/omg/CORBA/CompletionStatusHelper.java
index 43b6b8c10..bf1c37532 100644
--- a/org/omg/CORBA/CompletionStatusHelper.java
+++ b/org/omg/CORBA/CompletionStatusHelper.java
@@ -52,11 +52,6 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class CompletionStatusHelper
{
/**
- * The cached typecode value, computed once.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the {@link CompletionStatus} from the
* given {@link Any}. This implementation expects
* the integer (Corba long) value, stating the completion
@@ -125,16 +120,12 @@ public abstract class CompletionStatusHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- String[] members =
- new String[] { "COMPLETED_YES", "COMPLETED_NO", "COMPLETED_MAYBE" };
-
- typeCode =
- OrbRestricted.Singleton.create_enum_tc(id(), "CompletionStatus",
- members
- );
- }
- return typeCode;
+ String[] members =
+ new String[] { "COMPLETED_YES", "COMPLETED_NO", "COMPLETED_MAYBE" };
+
+ return
+ OrbRestricted.Singleton.create_enum_tc(id(), "CompletionStatus",
+ members
+ );
}
} \ No newline at end of file
diff --git a/org/omg/CORBA/CurrentHelper.java b/org/omg/CORBA/CurrentHelper.java
index 51bd65fc1..f292449ec 100644
--- a/org/omg/CORBA/CurrentHelper.java
+++ b/org/omg/CORBA/CurrentHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.CORBA;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
import org.omg.CORBA.ORB;
@@ -85,18 +87,12 @@ public abstract class CurrentHelper
}
/**
- * The cached {@link Current} typecode, computed once.
- */
- private static TypeCode typeCode;
-
- /**
* Get the type code of the {@link Current}.
*/
public static TypeCode type()
{
- if (typeCode == null)
- typeCode = ORB.init().create_interface_tc(id(), "Current");
- return typeCode;
+ return
+ OrbRestricted.Singleton.create_interface_tc(id(), "Current");
}
/**
diff --git a/org/omg/CORBA/DefinitionKindHelper.java b/org/omg/CORBA/DefinitionKindHelper.java
index fddbb585a..ef7e26725 100644
--- a/org/omg/CORBA/DefinitionKindHelper.java
+++ b/org/omg/CORBA/DefinitionKindHelper.java
@@ -55,11 +55,6 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class DefinitionKindHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Insert the definition kind into the given Any.
*/
public static void insert(Any a, DefinitionKind that)
@@ -83,25 +78,21 @@ public abstract class DefinitionKindHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- String[] members =
- new String[]
- {
- "dk_none", "dk_all", "dk_Attribute", "dk_Constant", "dk_Exception",
- "dk_Interface", "dk_Module", "dk_Operation", "dk_Typedef",
- "dk_Alias", "dk_Struct", "dk_Union", "dk_Enum", "dk_Primitive",
- "dk_String", "dk_Sequence", "dk_Array", "dk_Repository",
- "dk_Wstring", "dk_Fixed", "dk_Value", "dk_ValueBox",
- "dk_ValueMember", "dk_Native"
- };
-
- typeCode =
- OrbRestricted.Singleton.create_enum_tc(id(), "DefinitionKind",
- members
- );
- }
- return typeCode;
+ String[] members =
+ new String[]
+ {
+ "dk_none", "dk_all", "dk_Attribute", "dk_Constant", "dk_Exception",
+ "dk_Interface", "dk_Module", "dk_Operation", "dk_Typedef",
+ "dk_Alias", "dk_Struct", "dk_Union", "dk_Enum", "dk_Primitive",
+ "dk_String", "dk_Sequence", "dk_Array", "dk_Repository",
+ "dk_Wstring", "dk_Fixed", "dk_Value", "dk_ValueBox",
+ "dk_ValueMember", "dk_Native"
+ };
+
+ return
+ OrbRestricted.Singleton.create_enum_tc(id(), "DefinitionKind",
+ members
+ );
}
/**
diff --git a/org/omg/CORBA/IDLTypeHelper.java b/org/omg/CORBA/IDLTypeHelper.java
index 635168eb8..ff874947f 100644
--- a/org/omg/CORBA/IDLTypeHelper.java
+++ b/org/omg/CORBA/IDLTypeHelper.java
@@ -53,11 +53,6 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class IDLTypeHelper
{
/**
- * The cached typecode value, computed once.
- */
- private static TypeCode typeCode;
-
- /**
* Insert the IDL type into the given Any.
*/
public static void insert(Any a, IDLType that)
@@ -81,14 +76,8 @@ public abstract class IDLTypeHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- typeCode =
- OrbRestricted.Singleton.create_interface_tc(IDLTypeHelper.id(),
- "IDLType"
- );
- }
- return typeCode;
+ return OrbRestricted.Singleton.create_interface_tc(IDLTypeHelper.id(),
+ "IDLType");
}
/**
diff --git a/org/omg/CORBA/NameValuePairHelper.java b/org/omg/CORBA/NameValuePairHelper.java
index 5d2430b23..f6d933930 100644
--- a/org/omg/CORBA/NameValuePairHelper.java
+++ b/org/omg/CORBA/NameValuePairHelper.java
@@ -43,6 +43,7 @@ import gnu.CORBA.typecodes.AliasTypeCode;
import gnu.CORBA.typecodes.PrimitiveTypeCode;
import gnu.CORBA.typecodes.StringTypeCode;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.portable.InputStream;
import org.omg.CORBA.portable.OutputStream;
@@ -61,11 +62,6 @@ public abstract class NameValuePairHelper
private static String _id = "IDL:omg.org/CORBA/NameValuePair:1.0";
/**
- * The cached type code value.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the NameValuePair from the given {@link Any}.
*/
public static NameValuePair extract(Any a)
@@ -115,21 +111,18 @@ public abstract class NameValuePairHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- StructMember[] members = new StructMember[ 2 ];
+ StructMember[] members = new StructMember[2];
- TypeCode t_id =
- new AliasTypeCode(new StringTypeCode(TCKind.tk_string), "", "id");
+ TypeCode t_id = new AliasTypeCode(new StringTypeCode(TCKind.tk_string), "",
+ "id");
- members [ 0 ] = new StructMember("id", t_id, null);
+ members[0] = new StructMember("id", t_id, null);
- members [ 1 ] =
- new StructMember("value", new PrimitiveTypeCode(TCKind.tk_any), null);
+ members[1] = new StructMember("value",
+ new PrimitiveTypeCode(TCKind.tk_any), null);
- typeCode = ORB.init().create_struct_tc(id(), "NameValuePair", members);
- }
- return typeCode;
+ return OrbRestricted.Singleton.create_struct_tc(id(), "NameValuePair",
+ members);
}
/**
diff --git a/org/omg/CORBA/ObjectHelper.java b/org/omg/CORBA/ObjectHelper.java
index 220f2dace..f662a7888 100644
--- a/org/omg/CORBA/ObjectHelper.java
+++ b/org/omg/CORBA/ObjectHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CORBA;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import gnu.CORBA.typecodes.PrimitiveTypeCode;
import org.omg.CORBA.portable.InputStream;
@@ -51,8 +52,6 @@ import org.omg.CORBA.portable.OutputStream;
*/
public abstract class ObjectHelper
{
- static TypeCode typeCode;
-
/**
* Extract the array of object from the given {@link Any}.
*/
@@ -100,9 +99,7 @@ public abstract class ObjectHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- typeCode = ORB.init().get_primitive_tc(TCKind.tk_objref);
- return typeCode;
+ return OrbRestricted.Singleton.get_primitive_tc(TCKind.tk_objref);
}
/**
diff --git a/org/omg/CORBA/ParameterModeHelper.java b/org/omg/CORBA/ParameterModeHelper.java
index ac17a9235..c96ce94ac 100644
--- a/org/omg/CORBA/ParameterModeHelper.java
+++ b/org/omg/CORBA/ParameterModeHelper.java
@@ -54,11 +54,6 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class ParameterModeHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Insert the parameter mode into the given Any.
*/
public static void insert(Any any, ParameterMode that)
@@ -81,15 +76,11 @@ public abstract class ParameterModeHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
String[] members =
new String[] { "PARAM_IN", "PARAM_OUT", "PARAM_INOUT" };
- typeCode =
+ return
OrbRestricted.Singleton.create_enum_tc(id(), "ParameterMode", members);
- }
- return typeCode;
}
/**
diff --git a/org/omg/CORBA/PolicyErrorCodeHelper.java b/org/omg/CORBA/PolicyErrorCodeHelper.java
index ab7ac9547..6feabdcfd 100644
--- a/org/omg/CORBA/PolicyErrorCodeHelper.java
+++ b/org/omg/CORBA/PolicyErrorCodeHelper.java
@@ -106,7 +106,7 @@ public abstract class PolicyErrorCodeHelper
}
/**
- * Delegates call to {@link OutputStream.write_short()}.
+ * Delegates call to {@link OutputStream#write_short()}.
*/
public static void write(OutputStream ostream, short value)
{
diff --git a/org/omg/CORBA/PolicyErrorHelper.java b/org/omg/CORBA/PolicyErrorHelper.java
index 49db768cd..27b5b465e 100644
--- a/org/omg/CORBA/PolicyErrorHelper.java
+++ b/org/omg/CORBA/PolicyErrorHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CORBA;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -57,32 +58,23 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class PolicyErrorHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Create the PolicyError typecode. The typecode defines a structure, named
* "PolicyError", containing the {@link PolicyErrorCode} (alias int) field,
* named "reason".
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 1 ];
-
- TypeCode field;
-
- field =
- orb.create_alias_tc("IDL:omg.org/CORBA/PolicyErrorCode:1.0",
- "PolicyErrorCode", orb.get_primitive_tc(TCKind.tk_short)
- );
- members [ 0 ] = new StructMember("reason", field, null);
- typeCode = orb.create_exception_tc(id(), "PolicyError", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[ 1 ];
+
+ TypeCode field;
+
+ field =
+ orb.create_alias_tc("IDL:omg.org/CORBA/PolicyErrorCode:1.0",
+ "PolicyErrorCode", orb.get_primitive_tc(TCKind.tk_short)
+ );
+ members [ 0 ] = new StructMember("reason", field, null);
+ return orb.create_exception_tc(id(), "PolicyError", members);
}
/**
diff --git a/org/omg/CORBA/PolicyHelper.java b/org/omg/CORBA/PolicyHelper.java
index 66fb0aa08..53b56244e 100644
--- a/org/omg/CORBA/PolicyHelper.java
+++ b/org/omg/CORBA/PolicyHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CORBA;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -60,20 +61,13 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class PolicyHelper
{
/**
- * The cached {@link Policy} typecode, computed once.
- */
- private static TypeCode typeCode;
-
- /**
* Get the type code of the {@link Policy}.
*
* @return interface typecode, named "Policy".
*/
public static TypeCode type()
{
- if (typeCode == null)
- typeCode = ORB.init().create_interface_tc(id(), "Policy");
- return typeCode;
+ return OrbRestricted.Singleton.create_interface_tc(id(), "Policy");
}
/**
diff --git a/org/omg/CORBA/PolicyListHelper.java b/org/omg/CORBA/PolicyListHelper.java
index 6e4d329b8..da0135c02 100644
--- a/org/omg/CORBA/PolicyListHelper.java
+++ b/org/omg/CORBA/PolicyListHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CORBA;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -60,18 +61,11 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class PolicyListHelper
{
/**
- * The cached {@link Policy[]} typecode, computed once.
- */
- private static TypeCode typeCode;
-
- /**
* Get the type code of the {@link Policy[]}.
*/
public static TypeCode type()
{
- if (typeCode == null)
- typeCode = ORB.init().create_interface_tc(id(), "Policy[]");
- return typeCode;
+ return OrbRestricted.Singleton.create_interface_tc(id(), "Policy[]");
}
/**
diff --git a/org/omg/CORBA/PolicyTypeHelper.java b/org/omg/CORBA/PolicyTypeHelper.java
index dadd3a9e6..7d5f9bf76 100644
--- a/org/omg/CORBA/PolicyTypeHelper.java
+++ b/org/omg/CORBA/PolicyTypeHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.CORBA;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
import org.omg.CORBA.ORB;
@@ -65,7 +67,7 @@ public abstract class PolicyTypeHelper
*/
public static TypeCode type()
{
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
return orb.create_alias_tc(id(), "PolicyType",
orb.get_primitive_tc(TCKind.tk_ulong)
);
diff --git a/org/omg/CORBA/ServiceDetailHelper.java b/org/omg/CORBA/ServiceDetailHelper.java
index 58000f2c5..76fbda610 100644
--- a/org/omg/CORBA/ServiceDetailHelper.java
+++ b/org/omg/CORBA/ServiceDetailHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CORBA;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import gnu.CORBA.ServiceDetailHolder;
import org.omg.CORBA.portable.InputStream;
@@ -57,11 +58,6 @@ public abstract class ServiceDetailHelper
private static String _id = "IDL:omg.org/CORBA/ServiceDetail:1.0";
/**
- * The cached typecode value, computed once.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the service detail info from the given {@link Any}
*
* @param a the Any to extract from.
@@ -137,25 +133,21 @@ public abstract class ServiceDetailHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
-
- StructMember[] members = new StructMember[ 2 ];
-
- TypeCode type =
- orb.create_alias_tc(_id, "ServiceDetailType",
- orb.get_primitive_tc(TCKind.tk_ulong)
- );
- members [ 0 ] = new StructMember("service_detail_type", type, null);
-
- TypeCode data =
- orb.create_sequence_tc(0, orb.get_primitive_tc(TCKind.tk_octet));
- members [ 1 ] = new StructMember("service_detail", data, null);
-
- typeCode = orb.create_struct_tc(id(), "ServiceDetail", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+
+ StructMember[] members = new StructMember[ 2 ];
+
+ TypeCode type =
+ orb.create_alias_tc(_id, "ServiceDetailType",
+ orb.get_primitive_tc(TCKind.tk_ulong)
+ );
+ members [ 0 ] = new StructMember("service_detail_type", type, null);
+
+ TypeCode data =
+ orb.create_sequence_tc(0, orb.get_primitive_tc(TCKind.tk_octet));
+ members [ 1 ] = new StructMember("service_detail", data, null);
+
+ return orb.create_struct_tc(id(), "ServiceDetail", members);
}
/**
diff --git a/org/omg/CORBA/ServiceInformationHelper.java b/org/omg/CORBA/ServiceInformationHelper.java
index 78a21d182..f77378fd7 100644
--- a/org/omg/CORBA/ServiceInformationHelper.java
+++ b/org/omg/CORBA/ServiceInformationHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.CORBA;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.portable.InputStream;
import org.omg.CORBA.portable.OutputStream;
@@ -57,11 +59,6 @@ public abstract class ServiceInformationHelper
private static String _id = "IDL:org/omg/CORBA/ServiceInformation:1.0";
/**
- * The caches typecode value, computed once.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the service information from the given Any.
*/
public static ServiceInformation extract(Any a)
@@ -109,34 +106,30 @@ public abstract class ServiceInformationHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
-
- StructMember[] members = new StructMember[ 2 ];
- TypeCode member;
-
- member =
- orb.create_alias_tc("IDL:omg.org/CORBA/ServiceOptionSeq:1.0",
- "ServiceOptionSeq", LongSeqHelper.type()
- );
-
- members [ 0 ] = new StructMember("service_options", member, null);
-
- member = ServiceDetailHelper.type();
- member = orb.create_sequence_tc(0, member);
- member =
- orb.create_alias_tc("IDL:omg.org/CORBA/ServiceDetailSeq:1.0",
- "ServiceDetailSeq", member
- );
- members [ 1 ] = new StructMember("service_details", member, null);
-
- typeCode =
- orb.create_struct_tc(ServiceInformationHelper.id(),
- "ServiceInformation", members
- );
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+
+ StructMember[] members = new StructMember[ 2 ];
+ TypeCode member;
+
+ member =
+ orb.create_alias_tc("IDL:omg.org/CORBA/ServiceOptionSeq:1.0",
+ "ServiceOptionSeq", LongSeqHelper.type()
+ );
+
+ members [ 0 ] = new StructMember("service_options", member, null);
+
+ member = ServiceDetailHelper.type();
+ member = orb.create_sequence_tc(0, member);
+ member =
+ orb.create_alias_tc("IDL:omg.org/CORBA/ServiceDetailSeq:1.0",
+ "ServiceDetailSeq", member
+ );
+ members [ 1 ] = new StructMember("service_details", member, null);
+
+ return
+ orb.create_struct_tc(ServiceInformationHelper.id(),
+ "ServiceInformation", members
+ );
}
/**
diff --git a/org/omg/CORBA/SetOverrideTypeHelper.java b/org/omg/CORBA/SetOverrideTypeHelper.java
index 1fa1ef868..fb2c8235a 100644
--- a/org/omg/CORBA/SetOverrideTypeHelper.java
+++ b/org/omg/CORBA/SetOverrideTypeHelper.java
@@ -52,11 +52,6 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class SetOverrideTypeHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Insert the definition kind into the given Any.
*/
public static void insert(Any any, SetOverrideType that)
@@ -79,20 +74,16 @@ public abstract class SetOverrideTypeHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- String[] members =
- new String[]
- {
- "SET_OVERRIDE" ,"ADD_OVERRIDE"
- };
-
- typeCode =
- OrbRestricted.Singleton.create_enum_tc(id(), "SetOverrideType",
- members
- );
- }
- return typeCode;
+ String[] members =
+ new String[]
+ {
+ "SET_OVERRIDE" ,"ADD_OVERRIDE"
+ };
+
+ return
+ OrbRestricted.Singleton.create_enum_tc(id(), "SetOverrideType",
+ members
+ );
}
/**
diff --git a/org/omg/CORBA/StringValueHelper.java b/org/omg/CORBA/StringValueHelper.java
index 24e79ce57..5273f5cfb 100644
--- a/org/omg/CORBA/StringValueHelper.java
+++ b/org/omg/CORBA/StringValueHelper.java
@@ -66,11 +66,6 @@ public class StringValueHelper
private static final String id = "IDL:omg.org/CORBA/StringValue:1.0";
/**
- * The cached typecode value, computed once.
- */
- private static TypeCode typecode;
-
- /**
* The String typecode.
*/
private static final TypeCode tString =
@@ -175,18 +170,13 @@ public class StringValueHelper
}
/**
- * Create and return the value box typecode, named "StringValue",
- * with the content typecode being unbounded string.
+ * Create and return the value box typecode, named "StringValue", with the
+ * content typecode being unbounded string.
*/
public static TypeCode type()
{
- if (typecode == null)
- {
- ORB orb = OrbRestricted.Singleton;
- typecode =
- orb.create_value_box_tc(id(), "StringValue", tString);
- }
- return typecode;
+ ORB orb = OrbRestricted.Singleton;
+ return orb.create_value_box_tc(id(), "StringValue", tString);
}
/**
diff --git a/org/omg/CORBA/UnionMemberHelper.java b/org/omg/CORBA/UnionMemberHelper.java
index c599542fb..ef69329b7 100644
--- a/org/omg/CORBA/UnionMemberHelper.java
+++ b/org/omg/CORBA/UnionMemberHelper.java
@@ -94,7 +94,7 @@ public abstract class UnionMemberHelper
{
if (active)
{
- return ORB.init().create_recursive_tc(id());
+ return OrbRestricted.Singleton.create_recursive_tc(id());
}
active = true;
diff --git a/org/omg/CORBA/UnknownUserExceptionHelper.java b/org/omg/CORBA/UnknownUserExceptionHelper.java
index e93dc7403..0ca50cb88 100644
--- a/org/omg/CORBA/UnknownUserExceptionHelper.java
+++ b/org/omg/CORBA/UnknownUserExceptionHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CORBA;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -57,30 +58,21 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class UnknownUserExceptionHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Create the UnknownUserException typecode (structure,
* named "UnknownUserException", containing a single field of
* type {@link Any}, named "except".
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
StructMember[] members = new StructMember[ 1 ];
TypeCode field;
field = orb.get_primitive_tc(TCKind.tk_any);
members [ 0 ] = new StructMember("except", field, null);
- typeCode =
+ return
orb.create_exception_tc(id(), "UnknownUserException", members);
- }
- return typeCode;
}
/**
diff --git a/org/omg/CORBA/VisibilityHelper.java b/org/omg/CORBA/VisibilityHelper.java
index a09e5b686..a00f96e14 100644
--- a/org/omg/CORBA/VisibilityHelper.java
+++ b/org/omg/CORBA/VisibilityHelper.java
@@ -53,11 +53,6 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class VisibilityHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Insert the Visibility into the given Any.
* Uses {@link Any#insert_short}.
*/
@@ -80,14 +75,10 @@ public abstract class VisibilityHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
TypeCode tshort =
OrbRestricted.Singleton.get_primitive_tc(TCKind.tk_short);
- typeCode =
+ return
OrbRestricted.Singleton.create_alias_tc(id(), "Visibility", tshort);
- }
- return typeCode;
}
/**
diff --git a/org/omg/CORBA/WStringValueHelper.java b/org/omg/CORBA/WStringValueHelper.java
index 1c63a408e..17f23214c 100644
--- a/org/omg/CORBA/WStringValueHelper.java
+++ b/org/omg/CORBA/WStringValueHelper.java
@@ -66,11 +66,6 @@ public class WStringValueHelper
private static final String id = "IDL:omg.org/CORBA/WStringValue:1.0";
/**
- * The cached typecode value, computed once.
- */
- private static TypeCode typecode;
-
- /**
* The Wide String typecode.
*/
private static final TypeCode twString =
@@ -175,18 +170,13 @@ public class WStringValueHelper
}
/**
- * Create and return the value box typecode, named "WStringValue",
- * with the content typecode being unbounded string.
+ * Create and return the value box typecode, named "WStringValue", with the
+ * content typecode being unbounded string.
*/
public static TypeCode type()
{
- if (typecode == null)
- {
- ORB orb = OrbRestricted.Singleton;
- typecode =
- orb.create_value_box_tc(id(), "WStringValue", twString);
- }
- return typecode;
+ ORB orb = OrbRestricted.Singleton;
+ return orb.create_value_box_tc(id(), "WStringValue", twString);
}
/**
diff --git a/org/omg/CORBA/WrongTransactionHelper.java b/org/omg/CORBA/WrongTransactionHelper.java
index 5bb5baff2..27368a4c0 100644
--- a/org/omg/CORBA/WrongTransactionHelper.java
+++ b/org/omg/CORBA/WrongTransactionHelper.java
@@ -40,6 +40,7 @@ package org.omg.CORBA;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -58,23 +59,14 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class WrongTransactionHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Create the WrongTransaction typecode (structure,
* named "WrongTransaction"), no fields.
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 0 ];
- typeCode = orb.create_exception_tc(id(), "WrongTransaction", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[ 0 ];
+ return orb.create_exception_tc(id(), "WrongTransaction", members);
}
/* Every user exception with no user defined
diff --git a/org/omg/CosNaming/BindingHelper.java b/org/omg/CosNaming/BindingHelper.java
index b5b420772..86b077016 100644
--- a/org/omg/CosNaming/BindingHelper.java
+++ b/org/omg/CosNaming/BindingHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CosNaming;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -61,11 +62,6 @@ public abstract class BindingHelper
private static String _id = "IDL:omg.org/CosNaming/Binding:1.0";
/**
- * The cached type code value.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the binding from the given {@link Any}.
*/
public static Binding extract(Any a)
@@ -115,21 +111,17 @@ public abstract class BindingHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
-
- StructMember[] members = new StructMember[ 2 ];
- TypeCode member;
- member = NameComponentHelper.type();
- member = orb.create_sequence_tc(0, member);
- member = orb.create_alias_tc(NameHelper.id(), "Name", member);
- members [ 0 ] = new StructMember("binding_name", member, null);
- member = BindingTypeHelper.type();
- members [ 1 ] = new StructMember("binding_type", member, null);
- typeCode = orb.create_struct_tc(id(), "Binding", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+
+ StructMember[] members = new StructMember[ 2 ];
+ TypeCode member;
+ member = NameComponentHelper.type();
+ member = orb.create_sequence_tc(0, member);
+ member = orb.create_alias_tc(NameHelper.id(), "Name", member);
+ members [ 0 ] = new StructMember("binding_name", member, null);
+ member = BindingTypeHelper.type();
+ members [ 1 ] = new StructMember("binding_type", member, null);
+ return orb.create_struct_tc(id(), "Binding", members);
}
/**
diff --git a/org/omg/CosNaming/BindingIteratorHelper.java b/org/omg/CosNaming/BindingIteratorHelper.java
index 64f7b4dfa..cb17d5748 100644
--- a/org/omg/CosNaming/BindingIteratorHelper.java
+++ b/org/omg/CosNaming/BindingIteratorHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CosNaming;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -63,11 +64,6 @@ public abstract class BindingIteratorHelper
private static String _id = "IDL:omg.org/CosNaming/BindingIterator:1.0";
/**
- * The cached type code value.
- */
- private static TypeCode typeCode = null;
-
- /**
* Extract the binding iterator from the given {@link Any}.
*/
public static BindingIterator extract(Any a)
@@ -167,9 +163,7 @@ public abstract class BindingIteratorHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- typeCode = ORB.init().create_interface_tc(id(), "BindingIterator");
- return typeCode;
+ return OrbRestricted.Singleton.create_interface_tc(id(), "BindingIterator");
}
/**
diff --git a/org/omg/CosNaming/BindingListHelper.java b/org/omg/CosNaming/BindingListHelper.java
index 44fe39dca..de04989e0 100644
--- a/org/omg/CosNaming/BindingListHelper.java
+++ b/org/omg/CosNaming/BindingListHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.CosNaming;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
import org.omg.CORBA.ORB;
@@ -58,11 +60,6 @@ public abstract class BindingListHelper
private static String _id = "IDL:omg.org/CosNaming/BindingList:1.0";
/**
- * The cached binding list type code.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the array of bindings from the given {@link Any}.
*/
public static Binding[] extract(Any a)
@@ -112,13 +109,11 @@ public abstract class BindingListHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- typeCode = BindingHelper.type();
- typeCode = orb.create_sequence_tc(0, typeCode);
- typeCode = orb.create_alias_tc(id(), "BindingList", typeCode);
- }
+ TypeCode typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ typeCode = BindingHelper.type();
+ typeCode = orb.create_sequence_tc(0, typeCode);
+ typeCode = orb.create_alias_tc(id(), "BindingList", typeCode);
return typeCode;
}
diff --git a/org/omg/CosNaming/BindingTypeHelper.java b/org/omg/CosNaming/BindingTypeHelper.java
index 2f0dc71c4..8f456ee70 100644
--- a/org/omg/CosNaming/BindingTypeHelper.java
+++ b/org/omg/CosNaming/BindingTypeHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CosNaming;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -58,8 +59,6 @@ public abstract class BindingTypeHelper
* The binding type repository id.
*/
private static String id = "IDL:omg.org/CosNaming/BindingType:1.0";
- private static TypeCode typeCode = null;
-
/**
* Extract the binding type from the given {@link Any}.
*/
@@ -105,16 +104,10 @@ public abstract class BindingTypeHelper
/**
* Get the type code of this enumeration.
*/
- public static synchronized TypeCode type()
+ public static TypeCode type()
{
- if (typeCode == null)
- {
- typeCode =
- ORB.init().create_enum_tc(id(), "BindingType",
- new String[] { "nobject", "ncontext" }
- );
- }
- return typeCode;
+ return OrbRestricted.Singleton.create_enum_tc(id(), "BindingType",
+ new String[] { "nobject", "ncontext" });
}
/**
diff --git a/org/omg/CosNaming/NameComponentHelper.java b/org/omg/CosNaming/NameComponentHelper.java
index 8499edfe6..8127aa01d 100644
--- a/org/omg/CosNaming/NameComponentHelper.java
+++ b/org/omg/CosNaming/NameComponentHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CosNaming;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -61,11 +62,6 @@ public abstract class NameComponentHelper
private static String _id = "IDL:omg.org/CosNaming/NameComponent:1.0";
/**
- * The cached type code.
- */
- private static TypeCode typeCode = null;
-
- /**
* Extract the name component from this {@link Any}
*/
public static NameComponent extract(Any a)
@@ -116,22 +112,18 @@ public abstract class NameComponentHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
-
- StructMember[] members = new StructMember[ 2 ];
- TypeCode member;
- member = orb.create_string_tc(0);
- members [ 0 ] = new StructMember("id", member, null);
- member = orb.create_string_tc(0);
- members [ 1 ] = new StructMember("kind", member, null);
- typeCode =
- orb.create_struct_tc(NameComponentHelper.id(), "NameComponent",
- members
- );
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+
+ StructMember[] members = new StructMember[ 2 ];
+ TypeCode member;
+ member = orb.create_string_tc(0);
+ members [ 0 ] = new StructMember("id", member, null);
+ member = orb.create_string_tc(0);
+ members [ 1 ] = new StructMember("kind", member, null);
+ return
+ orb.create_struct_tc(NameComponentHelper.id(), "NameComponent",
+ members
+ );
}
/**
diff --git a/org/omg/CosNaming/NameHelper.java b/org/omg/CosNaming/NameHelper.java
index 18faf3182..f66fa4f09 100644
--- a/org/omg/CosNaming/NameHelper.java
+++ b/org/omg/CosNaming/NameHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CosNaming;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -62,11 +63,6 @@ public abstract class NameHelper
private static String _id = "IDL:omg.org/CosNaming/Name:1.0";
/**
- * The cached typecode of the Name.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the Name the given {@link Any}.
*/
public static NameComponent[] extract(Any a)
@@ -118,13 +114,11 @@ public abstract class NameHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- typeCode = NameComponentHelper.type();
- typeCode = ORB.init().create_sequence_tc(0, typeCode);
- typeCode =
- ORB.init().create_alias_tc(NameHelper.id(), "Name", typeCode);
- }
+ TypeCode typeCode;
+ typeCode = NameComponentHelper.type();
+ typeCode = OrbRestricted.Singleton.create_sequence_tc(0, typeCode);
+ typeCode =
+ OrbRestricted.Singleton.create_alias_tc(NameHelper.id(), "Name", typeCode);
return typeCode;
}
diff --git a/org/omg/CosNaming/NamingContextExtHelper.java b/org/omg/CosNaming/NamingContextExtHelper.java
index 86bf8c55d..aca0e9dfd 100644
--- a/org/omg/CosNaming/NamingContextExtHelper.java
+++ b/org/omg/CosNaming/NamingContextExtHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CosNaming;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -63,11 +64,6 @@ public abstract class NamingContextExtHelper
private static String _id = "IDL:omg.org/CosNaming/NamingContextExt:1.0";
/**
- * The cached {@link NamingContextExt} typecode.
- */
- private static TypeCode typeCode = null;
-
- /**
* Extract the naming context from the given {@link Any}.
*/
public static NamingContextExt extract(Any a)
@@ -168,12 +164,8 @@ public abstract class NamingContextExtHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- typeCode =
- ORB.init().create_interface_tc(NamingContextExtHelper.id(),
- "NamingContextExt"
- );
- return typeCode;
+ return OrbRestricted.Singleton.create_interface_tc(NamingContextExtHelper.id(),
+ "NamingContextExt");
}
/**
diff --git a/org/omg/CosNaming/NamingContextExtPackage/AddressHelper.java b/org/omg/CosNaming/NamingContextExtPackage/AddressHelper.java
index cf4029ccf..810460744 100644
--- a/org/omg/CosNaming/NamingContextExtPackage/AddressHelper.java
+++ b/org/omg/CosNaming/NamingContextExtPackage/AddressHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.CosNaming.NamingContextExtPackage;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.ORB;
import org.omg.CORBA.TypeCode;
@@ -60,11 +62,6 @@ public abstract class AddressHelper
"IDL:omg.org/CosNaming/NamingContextExt/Address:1.0";
/**
- * The cached type code (string alias).
- */
- private static TypeCode typeCode = null;
-
- /**
* Just extracts string from this {@link Any}.
*/
public static String extract(Any a)
@@ -99,13 +96,12 @@ public abstract class AddressHelper
/**
* Return the "Address", alias of String, typecode.
*/
- public static synchronized TypeCode type()
+ public static TypeCode type()
{
- if (typeCode == null)
- {
- typeCode = ORB.init().create_string_tc(0);
- typeCode = ORB.init().create_alias_tc(id(), "Address", typeCode);
- }
+ ORB orb = OrbRestricted.Singleton;
+ TypeCode typeCode;
+ typeCode = orb.create_string_tc(0);
+ typeCode = orb.create_alias_tc(id(), "Address", typeCode);
return typeCode;
}
diff --git a/org/omg/CosNaming/NamingContextExtPackage/InvalidAddressHelper.java b/org/omg/CosNaming/NamingContextExtPackage/InvalidAddressHelper.java
index 02f8fccb6..c7f3849a0 100644
--- a/org/omg/CosNaming/NamingContextExtPackage/InvalidAddressHelper.java
+++ b/org/omg/CosNaming/NamingContextExtPackage/InvalidAddressHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.CosNaming.NamingContextExtPackage;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.ORB;
import org.omg.CORBA.StructMember;
@@ -59,11 +61,6 @@ public abstract class InvalidAddressHelper
"IDL:omg.org/CosNaming/NamingContextExt/InvalidAddress:1.0";
/**
- * The cached type code value.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the exception from the given {@link Any}.
*/
public static InvalidAddress extract(Any a)
@@ -102,16 +99,10 @@ public abstract class InvalidAddressHelper
/**
* Create the type code for this exception.
*/
- public static synchronized TypeCode type()
+ public static TypeCode type()
{
- if (typeCode == null)
- {
- typeCode =
- ORB.init().create_struct_tc(InvalidAddressHelper.id(),
- "InvalidAddress", new StructMember[ 0 ]
- );
- }
- return typeCode;
+ return OrbRestricted.Singleton.create_struct_tc(InvalidAddressHelper.id(),
+ "InvalidAddress", new StructMember[0]);
}
public static void write(OutputStream ostream, InvalidAddress value)
diff --git a/org/omg/CosNaming/NamingContextExtPackage/StringNameHelper.java b/org/omg/CosNaming/NamingContextExtPackage/StringNameHelper.java
index 24c69fcb9..06faa2ff9 100644
--- a/org/omg/CosNaming/NamingContextExtPackage/StringNameHelper.java
+++ b/org/omg/CosNaming/NamingContextExtPackage/StringNameHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.CosNaming.NamingContextExtPackage;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.ORB;
import org.omg.CORBA.TypeCode;
@@ -61,11 +63,6 @@ public abstract class StringNameHelper
"IDL:omg.org/CosNaming/NamingContextExt/StringName:1.0";
/**
- * The cached type code (string alias).
- */
- private static TypeCode typeCode;
-
- /**
* Just extracts string from this {@link Any}.
*/
public static String extract(Any a)
@@ -100,13 +97,11 @@ public abstract class StringNameHelper
/**
* Return the "StringName", alias of String, typecode.
*/
- public static synchronized TypeCode type()
+ public static TypeCode type()
{
- if (typeCode == null)
- {
- typeCode = ORB.init().create_string_tc(0);
- typeCode = ORB.init().create_alias_tc(id(), "StringName", typeCode);
- }
+ TypeCode typeCode;
+ typeCode = OrbRestricted.Singleton.create_string_tc(0);
+ typeCode = OrbRestricted.Singleton.create_alias_tc(id(), "StringName", typeCode);
return typeCode;
}
diff --git a/org/omg/CosNaming/NamingContextExtPackage/URLStringHelper.java b/org/omg/CosNaming/NamingContextExtPackage/URLStringHelper.java
index 503fe22d6..173bb989e 100644
--- a/org/omg/CosNaming/NamingContextExtPackage/URLStringHelper.java
+++ b/org/omg/CosNaming/NamingContextExtPackage/URLStringHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.CosNaming.NamingContextExtPackage;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.ORB;
import org.omg.CORBA.TypeCode;
@@ -60,11 +62,6 @@ public abstract class URLStringHelper
"IDL:omg.org/CosNaming/NamingContextExt/URLString:1.0";
/**
- * The cached type code (string alias).
- */
- private static TypeCode typeCode;
-
- /**
* Just extracts string from this {@link Any}.
*/
public static String extract(Any a)
@@ -99,13 +96,11 @@ public abstract class URLStringHelper
/**
* Return the "URLString", alias of String, typecode.
*/
- public static synchronized TypeCode type()
+ public static TypeCode type()
{
- if (typeCode == null)
- {
- typeCode = ORB.init().create_string_tc(0);
- typeCode = ORB.init().create_alias_tc(id(), "URLString", typeCode);
- }
+ TypeCode typeCode;
+ typeCode = OrbRestricted.Singleton.create_string_tc(0);
+ typeCode = OrbRestricted.Singleton.create_alias_tc(id(), "URLString", typeCode);
return typeCode;
}
diff --git a/org/omg/CosNaming/NamingContextHelper.java b/org/omg/CosNaming/NamingContextHelper.java
index fb9b091a6..48b90c25a 100644
--- a/org/omg/CosNaming/NamingContextHelper.java
+++ b/org/omg/CosNaming/NamingContextHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CosNaming;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -63,11 +64,6 @@ public abstract class NamingContextHelper
private static String _id = "IDL:omg.org/CosNaming/NamingContext:1.0";
/**
- * The cached {@link NamingContext} typecode.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the naming context from the given {@link Any}.
*/
public static NamingContext extract(Any a)
@@ -176,9 +172,7 @@ public abstract class NamingContextHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- typeCode = ORB.init().create_interface_tc(id(), "NamingContext");
- return typeCode;
+ return OrbRestricted.Singleton.create_interface_tc(id(), "NamingContext");
}
/**
diff --git a/org/omg/CosNaming/NamingContextPackage/AlreadyBoundHelper.java b/org/omg/CosNaming/NamingContextPackage/AlreadyBoundHelper.java
index 6bf7bd7a6..f43111cb2 100644
--- a/org/omg/CosNaming/NamingContextPackage/AlreadyBoundHelper.java
+++ b/org/omg/CosNaming/NamingContextPackage/AlreadyBoundHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CosNaming.NamingContextPackage;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -62,11 +63,6 @@ public abstract class AlreadyBoundHelper
"IDL:omg.org/CosNaming/NamingContext/AlreadyBound:1.0";
/**
- * The cached type code value.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the exception from the given {@link Any}.
*/
public static AlreadyBound extract(Any a)
@@ -117,10 +113,8 @@ public abstract class AlreadyBoundHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- typeCode =
- ORB.init().create_struct_tc(id(), "AlreadyBound", new StructMember[ 0 ]);
- return typeCode;
+ return
+ OrbRestricted.Singleton.create_struct_tc(id(), "AlreadyBound", new StructMember[ 0 ]);
}
/**
diff --git a/org/omg/CosNaming/NamingContextPackage/CannotProceedHelper.java b/org/omg/CosNaming/NamingContextPackage/CannotProceedHelper.java
index 1d0b6049b..85e391cf8 100644
--- a/org/omg/CosNaming/NamingContextPackage/CannotProceedHelper.java
+++ b/org/omg/CosNaming/NamingContextPackage/CannotProceedHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CosNaming.NamingContextPackage;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -65,11 +66,6 @@ public abstract class CannotProceedHelper
"IDL:omg.org/CosNaming/NamingContext/CannotProceed:1.0";
/**
- * The cached type code value.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the exception from the given {@link Any}.
*/
public static CannotProceed extract(Any a)
@@ -122,21 +118,17 @@ public abstract class CannotProceedHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
-
- StructMember[] members = new StructMember[ 2 ];
- TypeCode member;
- member = NamingContextHelper.type();
- members [ 0 ] = new StructMember("cxt", member, null);
- member = NameComponentHelper.type();
- member = orb.create_sequence_tc(0, member);
- member = orb.create_alias_tc(NameHelper.id(), "Name", member);
- members [ 1 ] = new StructMember("rest_of_name", member, null);
- typeCode = orb.create_struct_tc(id(), "CannotProceed", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+
+ StructMember[] members = new StructMember[ 2 ];
+ TypeCode member;
+ member = NamingContextHelper.type();
+ members [ 0 ] = new StructMember("cxt", member, null);
+ member = NameComponentHelper.type();
+ member = orb.create_sequence_tc(0, member);
+ member = orb.create_alias_tc(NameHelper.id(), "Name", member);
+ members [ 1 ] = new StructMember("rest_of_name", member, null);
+ return orb.create_struct_tc(id(), "CannotProceed", members);
}
/**
diff --git a/org/omg/CosNaming/NamingContextPackage/InvalidNameHelper.java b/org/omg/CosNaming/NamingContextPackage/InvalidNameHelper.java
index 8f1133602..5893332b8 100644
--- a/org/omg/CosNaming/NamingContextPackage/InvalidNameHelper.java
+++ b/org/omg/CosNaming/NamingContextPackage/InvalidNameHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CosNaming.NamingContextPackage;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -62,11 +63,6 @@ public abstract class InvalidNameHelper
"IDL:omg.org/CosNaming/NamingContext/InvalidName:1.0";
/**
- * The cached type code value.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the exception from the given {@link Any}.
*/
public static InvalidName extract(Any a)
@@ -117,15 +113,8 @@ public abstract class InvalidNameHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- if (typeCode == null)
- typeCode =
- ORB.init().create_struct_tc(id(), "InvalidName",
- new StructMember[ 0 ]
- );
- }
- return typeCode;
+ return OrbRestricted.Singleton.create_struct_tc(id(),
+ "InvalidName", new StructMember[0]);
}
/**
diff --git a/org/omg/CosNaming/NamingContextPackage/NotEmptyHelper.java b/org/omg/CosNaming/NamingContextPackage/NotEmptyHelper.java
index 6333dfcbc..a9b802f95 100644
--- a/org/omg/CosNaming/NamingContextPackage/NotEmptyHelper.java
+++ b/org/omg/CosNaming/NamingContextPackage/NotEmptyHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CosNaming.NamingContextPackage;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -62,11 +63,6 @@ public abstract class NotEmptyHelper
"IDL:omg.org/CosNaming/NamingContext/NotEmpty:1.0";
/**
- * The cached type code value.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the exception from the given {@link Any}.
*/
public static NotEmpty extract(Any a)
@@ -117,10 +113,8 @@ public abstract class NotEmptyHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- typeCode =
- ORB.init().create_struct_tc(id(), "NotEmpty", new StructMember[ 0 ]);
- return typeCode;
+ return OrbRestricted.Singleton.create_struct_tc(id(),
+ "NotEmpty", new StructMember[0]);
}
/**
diff --git a/org/omg/CosNaming/NamingContextPackage/NotFoundHelper.java b/org/omg/CosNaming/NamingContextPackage/NotFoundHelper.java
index 442b7db9e..0be9b75bc 100644
--- a/org/omg/CosNaming/NamingContextPackage/NotFoundHelper.java
+++ b/org/omg/CosNaming/NamingContextPackage/NotFoundHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CosNaming.NamingContextPackage;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -64,11 +65,6 @@ public abstract class NotFoundHelper
"IDL:omg.org/CosNaming/NamingContext/NotFound:1.0";
/**
- * The cached type code value.
- */
- private static TypeCode typeCode = null;
-
- /**
* Extract the exception from the given {@link Any}.
*/
public static NotFound extract(Any a)
@@ -121,21 +117,17 @@ public abstract class NotFoundHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
-
- StructMember[] members = new StructMember[ 2 ];
- TypeCode member = null;
- member = NotFoundReasonHelper.type();
- members [ 0 ] = new StructMember("why", member, null);
- member = NameComponentHelper.type();
- member = orb.create_sequence_tc(0, member);
- member = orb.create_alias_tc(NameHelper.id(), "Name", member);
- members [ 1 ] = new StructMember("rest_of_name", member, null);
- typeCode = orb.create_struct_tc(id(), "NotFound", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+
+ StructMember[] members = new StructMember[ 2 ];
+ TypeCode member = null;
+ member = NotFoundReasonHelper.type();
+ members [ 0 ] = new StructMember("why", member, null);
+ member = NameComponentHelper.type();
+ member = orb.create_sequence_tc(0, member);
+ member = orb.create_alias_tc(NameHelper.id(), "Name", member);
+ members [ 1 ] = new StructMember("rest_of_name", member, null);
+ return orb.create_struct_tc(id(), "NotFound", members);
}
/**
diff --git a/org/omg/CosNaming/NamingContextPackage/NotFoundReasonHelper.java b/org/omg/CosNaming/NamingContextPackage/NotFoundReasonHelper.java
index 45a42a0ba..9d44dcbf3 100644
--- a/org/omg/CosNaming/NamingContextPackage/NotFoundReasonHelper.java
+++ b/org/omg/CosNaming/NamingContextPackage/NotFoundReasonHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.CosNaming.NamingContextPackage;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -61,11 +62,6 @@ public abstract class NotFoundReasonHelper
"IDL:omg.org/CosNaming/NamingContext/NotFoundReason:1.0";
/**
- * The cached type code value.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the exception from the given {@link Any}.
*/
public static NotFoundReason extract(Any a)
@@ -112,15 +108,15 @@ public abstract class NotFoundReasonHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- typeCode =
- ORB.init().create_enum_tc(id(), "NotFoundReason",
- new String[]
- {
- "missing_node", "not_context", "not_object"
- }
- );
- return typeCode;
+ return
+ OrbRestricted.Singleton.create_enum_tc(id(), "NotFoundReason",
+ new String[]
+ {
+ "missing_node",
+ "not_context",
+ "not_object"
+ }
+ );
}
/**
diff --git a/org/omg/DynamicAny/AnySeqHelper.java b/org/omg/DynamicAny/AnySeqHelper.java
index 60e4e6ea7..ddf1422ff 100644
--- a/org/omg/DynamicAny/AnySeqHelper.java
+++ b/org/omg/DynamicAny/AnySeqHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.DynamicAny;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.ORB;
import org.omg.CORBA.TCKind;
@@ -54,11 +56,6 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class AnySeqHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Delegates call to {@link org.omg.CORBA.AnySeqHelper#extract}.
*/
public static Any[] extract(Any any)
@@ -102,14 +99,10 @@ public abstract class AnySeqHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- TypeCode t =
- orb.create_sequence_tc(0, orb.get_primitive_tc(TCKind.tk_any));
- typeCode = orb.create_alias_tc(id(), "AnySeq", t);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ TypeCode t =
+ orb.create_sequence_tc(0, orb.get_primitive_tc(TCKind.tk_any));
+ return orb.create_alias_tc(id(), "AnySeq", t);
}
/**
diff --git a/org/omg/DynamicAny/DynAnyFactoryHelper.java b/org/omg/DynamicAny/DynAnyFactoryHelper.java
index b8e3aafef..97b54873f 100644
--- a/org/omg/DynamicAny/DynAnyFactoryHelper.java
+++ b/org/omg/DynamicAny/DynAnyFactoryHelper.java
@@ -40,6 +40,7 @@ exception statement from your version. */
package org.omg.DynamicAny;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.TypeCode;
@@ -107,7 +108,7 @@ public abstract class DynAnyFactoryHelper
*/
public static TypeCode type()
{
- return ORB.init().create_interface_tc(id(), "DynAnyFactory");
+ return OrbRestricted.Singleton.create_interface_tc(id(), "DynAnyFactory");
}
/**
diff --git a/org/omg/DynamicAny/DynAnyFactoryPackage/InconsistentTypeCodeHelper.java b/org/omg/DynamicAny/DynAnyFactoryPackage/InconsistentTypeCodeHelper.java
index a9f45c4b7..96dbb5fb6 100644
--- a/org/omg/DynamicAny/DynAnyFactoryPackage/InconsistentTypeCodeHelper.java
+++ b/org/omg/DynamicAny/DynAnyFactoryPackage/InconsistentTypeCodeHelper.java
@@ -40,6 +40,7 @@ package org.omg.DynamicAny.DynAnyFactoryPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -58,29 +59,19 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class InconsistentTypeCodeHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
- * Create the InconsistentTypeCode typecode (structure,
- * named "InconsistentTypeCode").
+ * Create the InconsistentTypeCode typecode (structure, named
+ * "InconsistentTypeCode").
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 0 ];
- typeCode =
- orb.create_exception_tc(id(), "InconsistentTypeCode", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[0];
+ return orb.create_exception_tc(id(), "InconsistentTypeCode", members);
}
/**
* Insert the InconsistentTypeCode into the given Any.
- *
+ *
* @param any the Any to insert into.
* @param that the InconsistentTypeCode to insert.
*/
diff --git a/org/omg/DynamicAny/DynAnyHelper.java b/org/omg/DynamicAny/DynAnyHelper.java
index 73e2d9856..a238bf48b 100644
--- a/org/omg/DynamicAny/DynAnyHelper.java
+++ b/org/omg/DynamicAny/DynAnyHelper.java
@@ -39,6 +39,8 @@ exception statement from your version. */
package org.omg.DynamicAny;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.ORB;
@@ -104,7 +106,7 @@ public abstract class DynAnyHelper
*/
public static TypeCode type()
{
- return ORB.init().create_interface_tc(id(), "DynAny");
+ return OrbRestricted.Singleton.create_interface_tc(id(), "DynAny");
}
/**
diff --git a/org/omg/DynamicAny/DynAnyPackage/InvalidValueHelper.java b/org/omg/DynamicAny/DynAnyPackage/InvalidValueHelper.java
index 1b5004f07..0258d3589 100644
--- a/org/omg/DynamicAny/DynAnyPackage/InvalidValueHelper.java
+++ b/org/omg/DynamicAny/DynAnyPackage/InvalidValueHelper.java
@@ -40,6 +40,7 @@ package org.omg.DynamicAny.DynAnyPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -58,23 +59,13 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class InvalidValueHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
- * Create the InvalidValue typecode (structure,
- * named "InvalidValue").
+ * Create the InvalidValue typecode (structure, named "InvalidValue").
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 0 ];
- typeCode = orb.create_exception_tc(id(), "InvalidValue", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[0];
+ return orb.create_exception_tc(id(), "InvalidValue", members);
}
/* Every user exception with no user defined
diff --git a/org/omg/DynamicAny/DynAnyPackage/TypeMismatchHelper.java b/org/omg/DynamicAny/DynAnyPackage/TypeMismatchHelper.java
index b09ab4db8..244a98aa0 100644
--- a/org/omg/DynamicAny/DynAnyPackage/TypeMismatchHelper.java
+++ b/org/omg/DynamicAny/DynAnyPackage/TypeMismatchHelper.java
@@ -40,6 +40,7 @@ package org.omg.DynamicAny.DynAnyPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -58,23 +59,13 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class TypeMismatchHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
- * Create the TypeMismatch typecode (structure,
- * named "TypeMismatch").
+ * Create the TypeMismatch typecode (structure, named "TypeMismatch").
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 0 ];
- typeCode = orb.create_exception_tc(id(), "TypeMismatch", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[0];
+ return orb.create_exception_tc(id(), "TypeMismatch", members);
}
/* Every user exception with no user defined
diff --git a/org/omg/DynamicAny/DynAnySeqHelper.java b/org/omg/DynamicAny/DynAnySeqHelper.java
index ec3f0c481..66208ea19 100644
--- a/org/omg/DynamicAny/DynAnySeqHelper.java
+++ b/org/omg/DynamicAny/DynAnySeqHelper.java
@@ -40,6 +40,7 @@ package org.omg.DynamicAny;
import gnu.CORBA.DynAnySeqHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -63,20 +64,11 @@ import org.omg.CORBA.portable.OutputStream;
*/
public abstract class DynAnySeqHelper
{
- /**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- TypeCode t = orb.create_sequence_tc(0, DynAnyHelper.type());
- typeCode = orb.create_alias_tc(id(), "DynAnySeq", t);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ TypeCode t = orb.create_sequence_tc(0, DynAnyHelper.type());
+ return orb.create_alias_tc(id(), "DynAnySeq", t);
}
/**
diff --git a/org/omg/DynamicAny/DynArrayHelper.java b/org/omg/DynamicAny/DynArrayHelper.java
index f2892c856..26824d747 100644
--- a/org/omg/DynamicAny/DynArrayHelper.java
+++ b/org/omg/DynamicAny/DynArrayHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.DynamicAny;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.ORB;
@@ -103,7 +105,7 @@ public abstract class DynArrayHelper
*/
public static TypeCode type()
{
- return ORB.init().create_interface_tc(id(), "DynArray");
+ return OrbRestricted.Singleton.create_interface_tc(id(), "DynArray");
}
/**
diff --git a/org/omg/DynamicAny/DynEnumHelper.java b/org/omg/DynamicAny/DynEnumHelper.java
index 8db1a2006..9af2e1194 100644
--- a/org/omg/DynamicAny/DynEnumHelper.java
+++ b/org/omg/DynamicAny/DynEnumHelper.java
@@ -39,6 +39,8 @@ exception statement from your version. */
package org.omg.DynamicAny;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.ORB;
@@ -104,7 +106,7 @@ public abstract class DynEnumHelper
*/
public static TypeCode type()
{
- return ORB.init().create_interface_tc(id(), "DynEnum");
+ return OrbRestricted.Singleton.create_interface_tc(id(), "DynEnum");
}
/**
diff --git a/org/omg/DynamicAny/DynFixedHelper.java b/org/omg/DynamicAny/DynFixedHelper.java
index 84bb59d9f..4471bb26b 100644
--- a/org/omg/DynamicAny/DynFixedHelper.java
+++ b/org/omg/DynamicAny/DynFixedHelper.java
@@ -39,6 +39,8 @@ exception statement from your version. */
package org.omg.DynamicAny;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.ORB;
@@ -104,7 +106,7 @@ public abstract class DynFixedHelper
*/
public static TypeCode type()
{
- return ORB.init().create_interface_tc(id(), "DynFixed");
+ return OrbRestricted.Singleton.create_interface_tc(id(), "DynFixed");
}
/**
diff --git a/org/omg/DynamicAny/DynSequenceHelper.java b/org/omg/DynamicAny/DynSequenceHelper.java
index ad3013371..0aa7cdd2a 100644
--- a/org/omg/DynamicAny/DynSequenceHelper.java
+++ b/org/omg/DynamicAny/DynSequenceHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.DynamicAny;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.ORB;
@@ -103,7 +105,7 @@ public abstract class DynSequenceHelper
*/
public static TypeCode type()
{
- return ORB.init().create_interface_tc(id(), "DynSequence");
+ return OrbRestricted.Singleton.create_interface_tc(id(), "DynSequence");
}
/**
diff --git a/org/omg/DynamicAny/DynStructHelper.java b/org/omg/DynamicAny/DynStructHelper.java
index 021c5d031..c683260f6 100644
--- a/org/omg/DynamicAny/DynStructHelper.java
+++ b/org/omg/DynamicAny/DynStructHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.DynamicAny;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.ORB;
@@ -103,7 +105,7 @@ public abstract class DynStructHelper
*/
public static TypeCode type()
{
- return ORB.init().create_interface_tc(id(), "DynStruct");
+ return OrbRestricted.Singleton.create_interface_tc(id(), "DynStruct");
}
/**
diff --git a/org/omg/DynamicAny/DynUnionHelper.java b/org/omg/DynamicAny/DynUnionHelper.java
index 8f924c086..e868ea412 100644
--- a/org/omg/DynamicAny/DynUnionHelper.java
+++ b/org/omg/DynamicAny/DynUnionHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.DynamicAny;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.ORB;
@@ -103,7 +105,7 @@ public abstract class DynUnionHelper
*/
public static TypeCode type()
{
- return ORB.init().create_interface_tc(id(), "DynUnion");
+ return OrbRestricted.Singleton.create_interface_tc(id(), "DynUnion");
}
/**
diff --git a/org/omg/DynamicAny/DynValueHelper.java b/org/omg/DynamicAny/DynValueHelper.java
index 026ca4990..ad75bc31f 100644
--- a/org/omg/DynamicAny/DynValueHelper.java
+++ b/org/omg/DynamicAny/DynValueHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.DynamicAny;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.ORB;
@@ -103,7 +105,7 @@ public abstract class DynValueHelper
*/
public static TypeCode type()
{
- return ORB.init().create_interface_tc(id(), "DynValue");
+ return OrbRestricted.Singleton.create_interface_tc(id(), "DynValue");
}
/**
diff --git a/org/omg/DynamicAny/NameDynAnyPairHelper.java b/org/omg/DynamicAny/NameDynAnyPairHelper.java
index a0e5c6b85..a9d9edba7 100644
--- a/org/omg/DynamicAny/NameDynAnyPairHelper.java
+++ b/org/omg/DynamicAny/NameDynAnyPairHelper.java
@@ -40,6 +40,7 @@ package org.omg.DynamicAny;
import gnu.CORBA.Minor;
import gnu.CORBA.NameDynAnyPairHolder;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -64,11 +65,6 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class NameDynAnyPairHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the NameDynAnyPair from given Any.
* This method uses the NameDynAnyPairHolder.
*
@@ -107,25 +103,21 @@ public abstract class NameDynAnyPairHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 2 ];
-
- TypeCode field;
-
- field =
- orb.create_alias_tc("IDL:omg.org/DynamicAny/FieldName:1.0",
- "FieldName",
- orb.get_primitive_tc(TCKind.tk_string)
- );
- members [ 0 ] = new StructMember("id", field, null);
-
- field = DynAnyHelper.type();
- members [ 1 ] = new StructMember("value", field, null);
- typeCode = orb.create_struct_tc(id(), "NameDynAnyPair", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[ 2 ];
+
+ TypeCode field;
+
+ field =
+ orb.create_alias_tc("IDL:omg.org/DynamicAny/FieldName:1.0",
+ "FieldName",
+ orb.get_primitive_tc(TCKind.tk_string)
+ );
+ members [ 0 ] = new StructMember("id", field, null);
+
+ field = DynAnyHelper.type();
+ members [ 1 ] = new StructMember("value", field, null);
+ return orb.create_struct_tc(id(), "NameDynAnyPair", members);
}
/**
diff --git a/org/omg/DynamicAny/NameDynAnyPairSeqHelper.java b/org/omg/DynamicAny/NameDynAnyPairSeqHelper.java
index ec4f72822..56e6104ec 100644
--- a/org/omg/DynamicAny/NameDynAnyPairSeqHelper.java
+++ b/org/omg/DynamicAny/NameDynAnyPairSeqHelper.java
@@ -40,6 +40,7 @@ package org.omg.DynamicAny;
import gnu.CORBA.Minor;
import gnu.CORBA.NameDynAnyPairSeqHolder;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -62,20 +63,11 @@ import org.omg.CORBA.portable.OutputStream;
*/
public abstract class NameDynAnyPairSeqHelper
{
- /**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- TypeCode t = orb.create_sequence_tc(0, NameDynAnyPairHelper.type());
- typeCode = orb.create_alias_tc(id(), "NameDynAnyPairSeq", t);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ TypeCode t = orb.create_sequence_tc(0, NameDynAnyPairHelper.type());
+ return orb.create_alias_tc(id(), "NameDynAnyPairSeq", t);
}
/**
diff --git a/org/omg/DynamicAny/NameValuePairHelper.java b/org/omg/DynamicAny/NameValuePairHelper.java
index 1e0f52b59..75bbf9a74 100644
--- a/org/omg/DynamicAny/NameValuePairHelper.java
+++ b/org/omg/DynamicAny/NameValuePairHelper.java
@@ -40,6 +40,7 @@ package org.omg.DynamicAny;
import gnu.CORBA.Minor;
import gnu.CORBA.NameValuePairHolder;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -58,11 +59,6 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class NameValuePairHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Create the NameValuePair typecode (structure,
* named "NameValuePair").
* The typecode states that the structure contains the
@@ -70,25 +66,21 @@ public abstract class NameValuePairHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 2 ];
-
- TypeCode field;
-
- field =
- orb.create_alias_tc("IDL:omg.org/DynamicAny/FieldName:1.0",
- "FieldName",
- orb.get_primitive_tc(TCKind.tk_string)
- );
- members [ 0 ] = new StructMember("id", field, null);
-
- field = orb.get_primitive_tc(TCKind.tk_any);
- members [ 1 ] = new StructMember("value", field, null);
- typeCode = orb.create_struct_tc(id(), "NameValuePair", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[ 2 ];
+
+ TypeCode field;
+
+ field =
+ orb.create_alias_tc("IDL:omg.org/DynamicAny/FieldName:1.0",
+ "FieldName",
+ orb.get_primitive_tc(TCKind.tk_string)
+ );
+ members [ 0 ] = new StructMember("id", field, null);
+
+ field = orb.get_primitive_tc(TCKind.tk_any);
+ members [ 1 ] = new StructMember("value", field, null);
+ return orb.create_struct_tc(id(), "NameValuePair", members);
}
/**
diff --git a/org/omg/DynamicAny/NameValuePairSeqHelper.java b/org/omg/DynamicAny/NameValuePairSeqHelper.java
index 62481534e..018ee7d2d 100644
--- a/org/omg/DynamicAny/NameValuePairSeqHelper.java
+++ b/org/omg/DynamicAny/NameValuePairSeqHelper.java
@@ -40,6 +40,7 @@ package org.omg.DynamicAny;
import gnu.CORBA.Minor;
import gnu.CORBA.NameValuePairSeqHolder;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -55,20 +56,11 @@ import org.omg.CORBA.portable.OutputStream;
*/
public abstract class NameValuePairSeqHelper
{
- /**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- TypeCode t = orb.create_sequence_tc(0, NameValuePairHelper.type());
- typeCode = orb.create_alias_tc(id(), "NameValuePairSeq", t);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ TypeCode t = orb.create_sequence_tc(0, NameValuePairHelper.type());
+ return orb.create_alias_tc(id(), "NameValuePairSeq", t);
}
/**
diff --git a/org/omg/IOP/CodecFactoryHelper.java b/org/omg/IOP/CodecFactoryHelper.java
index fea0b887b..89404f7d5 100644
--- a/org/omg/IOP/CodecFactoryHelper.java
+++ b/org/omg/IOP/CodecFactoryHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.IOP;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.CompletionStatus;
@@ -56,18 +58,11 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class CodecFactoryHelper
{
/**
- * The cached {@link CodecFactory} typecode, computed once.
- */
- private static TypeCode typeCode;
-
- /**
* Get the type code of the {@link CodecFactory}.
*/
public static TypeCode type()
{
- if (typeCode == null)
- typeCode = ORB.init().create_interface_tc(id(), "CodecFactory");
- return typeCode;
+ return OrbRestricted.Singleton.create_interface_tc(id(), "CodecFactory");
}
/**
diff --git a/org/omg/IOP/CodecFactoryPackage/UnknownEncodingHelper.java b/org/omg/IOP/CodecFactoryPackage/UnknownEncodingHelper.java
index e036dbf1f..8861e43da 100644
--- a/org/omg/IOP/CodecFactoryPackage/UnknownEncodingHelper.java
+++ b/org/omg/IOP/CodecFactoryPackage/UnknownEncodingHelper.java
@@ -40,6 +40,7 @@ package org.omg.IOP.CodecFactoryPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Any;
@@ -59,25 +60,16 @@ import org.omg.CORBA.BAD_OPERATION;
public abstract class UnknownEncodingHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Create the UnknownEncoding typecode (structure,
* named "UnknownEncoding").
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[0];
- typeCode =
- orb.create_exception_tc (id(), "UnknownEncoding", members);
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[0];
+ return
+ orb.create_exception_tc (id(), "UnknownEncoding", members);
- }
- return typeCode;
}
/* Every user exception with no user defined fields can use EmptyExceptionHolder */
diff --git a/org/omg/IOP/CodecPackage/FormatMismatchHelper.java b/org/omg/IOP/CodecPackage/FormatMismatchHelper.java
index e353be8f9..2a9295ae8 100644
--- a/org/omg/IOP/CodecPackage/FormatMismatchHelper.java
+++ b/org/omg/IOP/CodecPackage/FormatMismatchHelper.java
@@ -40,6 +40,7 @@ package org.omg.IOP.CodecPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -58,23 +59,14 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class FormatMismatchHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Create the FormatMismatch typecode (structure,
* named "FormatMismatch").
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 0 ];
- typeCode = orb.create_exception_tc(id(), "FormatMismatch", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[ 0 ];
+ return orb.create_exception_tc(id(), "FormatMismatch", members);
}
/**
diff --git a/org/omg/IOP/CodecPackage/InvalidTypeForEncodingHelper.java b/org/omg/IOP/CodecPackage/InvalidTypeForEncodingHelper.java
index 8a93c5895..e2a8c9057 100644
--- a/org/omg/IOP/CodecPackage/InvalidTypeForEncodingHelper.java
+++ b/org/omg/IOP/CodecPackage/InvalidTypeForEncodingHelper.java
@@ -40,6 +40,7 @@ package org.omg.IOP.CodecPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -58,29 +59,19 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class InvalidTypeForEncodingHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
- * Create the InvalidTypeForEncoding typecode (structure,
- * named "InvalidTypeForEncoding").
+ * Create the InvalidTypeForEncoding typecode (structure, named
+ * "InvalidTypeForEncoding").
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 0 ];
- typeCode =
- orb.create_exception_tc(id(), "InvalidTypeForEncoding", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[0];
+ return orb.create_exception_tc(id(), "InvalidTypeForEncoding", members);
}
/**
* Insert the InvalidTypeForEncoding into the given Any.
- *
+ *
* @param any the Any to insert into.
* @param that the InvalidTypeForEncoding to insert.
*/
diff --git a/org/omg/IOP/CodecPackage/TypeMismatchHelper.java b/org/omg/IOP/CodecPackage/TypeMismatchHelper.java
index 33951de70..432e84d24 100644
--- a/org/omg/IOP/CodecPackage/TypeMismatchHelper.java
+++ b/org/omg/IOP/CodecPackage/TypeMismatchHelper.java
@@ -40,6 +40,7 @@ package org.omg.IOP.CodecPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -58,23 +59,14 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class TypeMismatchHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Create the TypeMismatch typecode (structure,
* named "TypeMismatch").
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 0 ];
- typeCode = orb.create_exception_tc(id(), "TypeMismatch", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[ 0 ];
+ return orb.create_exception_tc(id(), "TypeMismatch", members);
}
/**
diff --git a/org/omg/IOP/ComponentIdHelper.java b/org/omg/IOP/ComponentIdHelper.java
index 64fbdfd74..35ffd9a69 100644
--- a/org/omg/IOP/ComponentIdHelper.java
+++ b/org/omg/IOP/ComponentIdHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.IOP;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
import org.omg.CORBA.ORB;
@@ -65,10 +67,10 @@ public abstract class ComponentIdHelper
*/
public static TypeCode type()
{
- ORB orb = ORB.init();
- return orb.create_alias_tc("IDL:omg.org/IOP/ComponentId:1.0", "ComponentId",
- orb.get_primitive_tc(TCKind.tk_ulong)
- );
+ ORB orb = OrbRestricted.Singleton;
+ return orb.create_alias_tc("IDL:omg.org/IOP/ComponentId:1.0",
+ "ComponentId",
+ orb.get_primitive_tc(TCKind.tk_ulong));
}
/**
diff --git a/org/omg/IOP/IORHelper.java b/org/omg/IOP/IORHelper.java
index 77f18d9b9..197e15a12 100644
--- a/org/omg/IOP/IORHelper.java
+++ b/org/omg/IOP/IORHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.IOP;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -57,42 +58,30 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class IORHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
- * Create the IOR typecode (structure,
- * named "IOR").
- * The typecode states that the structure contains the
- * following fields: type_id, profiles.
+ * Create the IOR typecode (structure, named "IOR"). The typecode states that
+ * the structure contains the following fields: type_id, profiles.
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 2 ];
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[2];
- TypeCode field;
+ TypeCode field;
- field = orb.get_primitive_tc(TCKind.tk_string);
- members [ 0 ] = new StructMember("type_id", field, null);
+ field = orb.get_primitive_tc(TCKind.tk_string);
+ members[0] = new StructMember("type_id", field, null);
- field = orb.create_sequence_tc(0, TaggedProfileHelper.type());
- members [ 1 ] = new StructMember("profiles", field, null);
- typeCode = orb.create_struct_tc(id(), "IOR", members);
- }
- return typeCode;
+ field = orb.create_sequence_tc(0, TaggedProfileHelper.type());
+ members[1] = new StructMember("profiles", field, null);
+ return orb.create_struct_tc(id(), "IOR", members);
}
/**
- * Insert the IOR into the given Any.
- * This method uses the IORHolder.
- *
- * @param any the Any to insert into.
- * @param that the IOR to insert.
- */
+ * Insert the IOR into the given Any. This method uses the IORHolder.
+ *
+ * @param any the Any to insert into.
+ * @param that the IOR to insert.
+ */
public static void insert(Any any, IOR that)
{
any.insert_Streamable(new IORHolder(that));
diff --git a/org/omg/IOP/MultipleComponentProfileHelper.java b/org/omg/IOP/MultipleComponentProfileHelper.java
index 6f5156fe2..1c04ec54f 100644
--- a/org/omg/IOP/MultipleComponentProfileHelper.java
+++ b/org/omg/IOP/MultipleComponentProfileHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.IOP;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Any;
@@ -57,24 +58,15 @@ import org.omg.CORBA.portable.InputStream;
*/
public abstract class MultipleComponentProfileHelper
{
- /**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- typeCode = orb.create_sequence_tc(0, TaggedComponentHelper.type());
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ return orb.create_sequence_tc(0, TaggedComponentHelper.type());
}
/**
- * Insert the MultipleComponentProfile into the given Any.
- * This method uses the MultipleComponentProfileHolder.
- *
+ * Insert the MultipleComponentProfile into the given Any. This method uses
+ * the MultipleComponentProfileHolder.
+ *
* @param any the Any to insert into.
* @param those the TaggedComponent[] to insert.
*/
diff --git a/org/omg/IOP/ProfileIdHelper.java b/org/omg/IOP/ProfileIdHelper.java
index 2e3c8f08d..340fa27d5 100644
--- a/org/omg/IOP/ProfileIdHelper.java
+++ b/org/omg/IOP/ProfileIdHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.IOP;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
import org.omg.CORBA.ORB;
@@ -65,15 +67,14 @@ public abstract class ProfileIdHelper
*/
public static TypeCode type()
{
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
return orb.create_alias_tc("IDL:omg.org/IOP/ProfileId:1.0", "ProfileId",
- orb.get_primitive_tc(TCKind.tk_ulong)
- );
+ orb.get_primitive_tc(TCKind.tk_ulong));
}
/**
- * Insert the int into the given Any.
- */
+ * Insert the int into the given Any.
+ */
public static void insert(Any any, int that)
{
any.insert_ulong(that);
diff --git a/org/omg/IOP/ServiceContextHelper.java b/org/omg/IOP/ServiceContextHelper.java
index 5693a3235..d6549fa54 100644
--- a/org/omg/IOP/ServiceContextHelper.java
+++ b/org/omg/IOP/ServiceContextHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.IOP;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -57,46 +58,33 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class ServiceContextHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
- * Create the ServiceContext typecode (structure,
- * named "ServiceContext").
- * The typecode states that the structure contains the
- * following fields: context_id, context_data.
+ * Create the ServiceContext typecode (structure, named "ServiceContext"). The
+ * typecode states that the structure contains the following fields:
+ * context_id, context_data.
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 2 ];
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[2];
- TypeCode field;
+ TypeCode field;
- field =
- orb.create_alias_tc("IDL:omg.org/IOP/ServiceId:1.0", "ServiceId",
- orb.get_primitive_tc(TCKind.tk_ulong)
- );
- members [ 0 ] = new StructMember("context_id", field, null);
+ field = orb.create_alias_tc("IDL:omg.org/IOP/ServiceId:1.0", "ServiceId",
+ orb.get_primitive_tc(TCKind.tk_ulong));
+ members[0] = new StructMember("context_id", field, null);
- field =
- orb.create_sequence_tc(0, orb.get_primitive_tc(TCKind.tk_octet));
- members [ 1 ] = new StructMember("context_data", field, null);
- typeCode = orb.create_struct_tc(id(), "ServiceContext", members);
- }
- return typeCode;
+ field = orb.create_sequence_tc(0, orb.get_primitive_tc(TCKind.tk_octet));
+ members[1] = new StructMember("context_data", field, null);
+ return orb.create_struct_tc(id(), "ServiceContext", members);
}
/**
- * Insert the ServiceContext into the given Any.
- * This method uses the ServiceContextHolder.
- *
- * @param any the Any to insert into.
- * @param that the ServiceContext to insert.
- */
+ * Insert the ServiceContext into the given Any. This method uses the
+ * ServiceContextHolder.
+ *
+ * @param any the Any to insert into.
+ * @param that the ServiceContext to insert.
+ */
public static void insert(Any any, ServiceContext that)
{
any.insert_Streamable(new ServiceContextHolder(that));
diff --git a/org/omg/IOP/ServiceContextListHelper.java b/org/omg/IOP/ServiceContextListHelper.java
index fa436cbb8..7875db29e 100644
--- a/org/omg/IOP/ServiceContextListHelper.java
+++ b/org/omg/IOP/ServiceContextListHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.IOP;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -56,18 +57,12 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class ServiceContextListHelper
{
/**
- * The cached {@link ServiceContext[]} typecode, computed once.
- */
- private static TypeCode typeCode;
-
- /**
* Get the type code of the {@link ServiceContext[]}.
*/
public static TypeCode type()
{
- if (typeCode == null)
- typeCode = ORB.init().create_interface_tc(id(), "ServiceContextList");
- return typeCode;
+ return OrbRestricted.Singleton.create_interface_tc(id(),
+ "ServiceContextList");
}
/**
diff --git a/org/omg/IOP/ServiceIdHelper.java b/org/omg/IOP/ServiceIdHelper.java
index fac0746a8..084dbd06d 100644
--- a/org/omg/IOP/ServiceIdHelper.java
+++ b/org/omg/IOP/ServiceIdHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.IOP;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
import org.omg.CORBA.ORB;
@@ -65,7 +67,7 @@ public abstract class ServiceIdHelper
*/
public static TypeCode type()
{
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
return orb.create_alias_tc("IDL:omg.org/IOP/ServiceId:1.0", "ServiceId",
orb.get_primitive_tc(TCKind.tk_ulong)
);
diff --git a/org/omg/IOP/TaggedComponentHelper.java b/org/omg/IOP/TaggedComponentHelper.java
index eaee120f0..633891b9b 100644
--- a/org/omg/IOP/TaggedComponentHelper.java
+++ b/org/omg/IOP/TaggedComponentHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.IOP;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -60,34 +61,25 @@ import java.io.IOException;
public abstract class TaggedComponentHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Create the TaggedComponent typecode (structure, named "TaggedComponent").
* The typecode states that the structure contains the following fields: tag,
* component_data.
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[2];
-
- TypeCode field;
-
- field = orb.create_alias_tc("IDL:omg.org/IOP/ComponentId:1.0",
- "ComponentId",
- orb.get_primitive_tc(TCKind.tk_ulong));
- members[0] = new StructMember("tag", field, null);
-
- field = orb.create_sequence_tc(0, orb.get_primitive_tc(TCKind.tk_octet));
- members[1] = new StructMember("component_data", field, null);
- typeCode = orb.create_struct_tc(id(), "TaggedComponent", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[2];
+
+ TypeCode field;
+
+ field = orb.create_alias_tc("IDL:omg.org/IOP/ComponentId:1.0",
+ "ComponentId",
+ orb.get_primitive_tc(TCKind.tk_ulong));
+ members[0] = new StructMember("tag", field, null);
+
+ field = orb.create_sequence_tc(0, orb.get_primitive_tc(TCKind.tk_octet));
+ members[1] = new StructMember("component_data", field, null);
+ return orb.create_struct_tc(id(), "TaggedComponent", members);
}
/**
diff --git a/org/omg/IOP/TaggedProfileHelper.java b/org/omg/IOP/TaggedProfileHelper.java
index 2943657c0..9dbbfdaff 100644
--- a/org/omg/IOP/TaggedProfileHelper.java
+++ b/org/omg/IOP/TaggedProfileHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.IOP;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import gnu.CORBA.CDR.BufferredCdrInput;
import gnu.CORBA.CDR.BufferedCdrOutput;
@@ -62,40 +63,30 @@ import java.io.IOException;
public abstract class TaggedProfileHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Create the TaggedProfile typecode (structure, named "TaggedProfile"). The
* typecode states that the structure contains the following fields: tag,
* profile_data.
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[2];
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[2];
- TypeCode field;
+ TypeCode field;
- field = orb.create_alias_tc("IDL:omg.org/IOP/ProfileId:1.0",
- "ProfileId",
- orb.get_primitive_tc(TCKind.tk_ulong));
- members[0] = new StructMember("tag", field, null);
+ field = orb.create_alias_tc("IDL:omg.org/IOP/ProfileId:1.0", "ProfileId",
+ orb.get_primitive_tc(TCKind.tk_ulong));
+ members[0] = new StructMember("tag", field, null);
- field = orb.create_sequence_tc(0, orb.get_primitive_tc(TCKind.tk_octet));
- members[1] = new StructMember("profile_data", field, null);
- typeCode = orb.create_struct_tc(id(), "TaggedProfile", members);
- }
- return typeCode;
+ field = orb.create_sequence_tc(0, orb.get_primitive_tc(TCKind.tk_octet));
+ members[1] = new StructMember("profile_data", field, null);
+ return orb.create_struct_tc(id(), "TaggedProfile", members);
}
/**
* Insert the TaggedProfile into the given Any. This method uses the
* TaggedProfileHolder.
- *
+ *
* @param any the Any to insert into.
* @param that the TaggedProfile to insert.
*/
diff --git a/org/omg/PortableInterceptor/AdapterManagerIdHelper.java b/org/omg/PortableInterceptor/AdapterManagerIdHelper.java
index f3f7e6441..936e6bc1b 100644
--- a/org/omg/PortableInterceptor/AdapterManagerIdHelper.java
+++ b/org/omg/PortableInterceptor/AdapterManagerIdHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.PortableInterceptor;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
import org.omg.CORBA.ORB;
@@ -57,15 +59,14 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class AdapterManagerIdHelper
{
/**
- * Create the AdapterManagerId typecode (alias of CORBA long (java int),
- * named "AdapterManagerId").
+ * Create the AdapterManagerId typecode (alias of CORBA long (java int), named
+ * "AdapterManagerId").
*/
public static TypeCode type()
{
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
return orb.create_alias_tc(id(), "AdapterManagerId",
- orb.get_primitive_tc(TCKind.tk_long)
- );
+ orb.get_primitive_tc(TCKind.tk_long));
}
/**
diff --git a/org/omg/PortableInterceptor/AdapterNameHelper.java b/org/omg/PortableInterceptor/AdapterNameHelper.java
index 1cda311b2..05844560a 100644
--- a/org/omg/PortableInterceptor/AdapterNameHelper.java
+++ b/org/omg/PortableInterceptor/AdapterNameHelper.java
@@ -61,11 +61,6 @@ public abstract class AdapterNameHelper
{
/**
- * The cached typecode, computed once.
- */
- static TypeCode typecode;
-
- /**
* Extract the adapter name (<code>String[]</code>) from the given {@link Any}.
*
* @param a an Any to extract the array from.
@@ -114,26 +109,22 @@ public abstract class AdapterNameHelper
}
/**
- * Creates and returns a new instance of the TypeCode,
- * corresponding the adapter name.
+ * Creates and returns a new instance of the TypeCode, corresponding the
+ * adapter name.
*
* @return the alias of the string sequence, named "AdapterName".
*/
public static TypeCode type()
{
- if (typecode == null)
- {
- ORB orb = OrbRestricted.Singleton;
-
- TypeCode component = orb.create_string_tc(0);
- typecode = orb.create_alias_tc(id(), "AdapterName", component);
- }
- return typecode;
+ ORB orb = OrbRestricted.Singleton;
+
+ TypeCode component = orb.create_string_tc(0);
+ return orb.create_alias_tc(id(), "AdapterName", component);
}
/**
* Writes the <code>String[]</code> into the given stream.
- *
+ *
* @param output the CORBA output stream to write.
* @param value the value that must be written.
*/
diff --git a/org/omg/PortableInterceptor/AdapterStateHelper.java b/org/omg/PortableInterceptor/AdapterStateHelper.java
index ceb7ac8d5..f0522caac 100644
--- a/org/omg/PortableInterceptor/AdapterStateHelper.java
+++ b/org/omg/PortableInterceptor/AdapterStateHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.PortableInterceptor;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
import org.omg.CORBA.ORB;
@@ -62,7 +64,7 @@ public abstract class AdapterStateHelper
*/
public static TypeCode type()
{
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
return orb.create_alias_tc(id(), "AdapterState",
orb.get_primitive_tc(TCKind.tk_short)
);
diff --git a/org/omg/PortableInterceptor/CurrentHelper.java b/org/omg/PortableInterceptor/CurrentHelper.java
index df3bcaef7..e453f6010 100644
--- a/org/omg/PortableInterceptor/CurrentHelper.java
+++ b/org/omg/PortableInterceptor/CurrentHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.PortableInterceptor;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_PARAM;
@@ -57,20 +58,11 @@ import org.omg.PortableServer.ServantActivator;
public abstract class CurrentHelper
{
/**
- * The cached {@link Current} typecode, computed once.
- */
- private static TypeCode typeCode;
-
- /**
* Get the type code of the {@link Current}.
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- typeCode = ORB.init().create_interface_tc(id(), "Current");
- }
- return typeCode;
+ return OrbRestricted.Singleton.create_interface_tc(id(), "Current");
}
/**
diff --git a/org/omg/PortableInterceptor/ForwardRequestHelper.java b/org/omg/PortableInterceptor/ForwardRequestHelper.java
index 5db56d745..8aa19a991 100644
--- a/org/omg/PortableInterceptor/ForwardRequestHelper.java
+++ b/org/omg/PortableInterceptor/ForwardRequestHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.PortableInterceptor;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import gnu.CORBA.Interceptor.ForwardRequestHolder;
import org.omg.CORBA.Any;
@@ -58,32 +59,23 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class ForwardRequestHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
- * Create the ForwardRequest typecode (structure, named "ForwardRequest"). The
+ * Create the ForwardRequest typecode (structure, named "ForwardRequest"). The
* typecode states that the structure contains the following fields: forward.
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 1 ];
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[1];
- TypeCode field = ObjectHelper.type();
- members [ 0 ] = new StructMember("forward", field, null);
- typeCode = orb.create_exception_tc(id(), "ForwardRequest", members);
- }
- return typeCode;
+ TypeCode field = ObjectHelper.type();
+ members[0] = new StructMember("forward", field, null);
+ return orb.create_exception_tc(id(), "ForwardRequest", members);
}
/**
* Insert the ForwardRequest into the given Any. This method uses the
* ForwardRequestHolder.
- *
+ *
* @param any the Any to insert into.
* @param that the ForwardRequest to insert.
*/
diff --git a/org/omg/PortableInterceptor/IORInterceptor_3_0Helper.java b/org/omg/PortableInterceptor/IORInterceptor_3_0Helper.java
index 565242477..926974f1a 100644
--- a/org/omg/PortableInterceptor/IORInterceptor_3_0Helper.java
+++ b/org/omg/PortableInterceptor/IORInterceptor_3_0Helper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.PortableInterceptor;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -60,18 +61,12 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class IORInterceptor_3_0Helper
{
/**
- * The cached {@link IORInterceptor_3_0} typecode, computed once.
- */
- private static TypeCode typeCode;
-
- /**
* Get the type code of the {@link IORInterceptor_3_0}.
*/
public static TypeCode type()
{
- if (typeCode == null)
- typeCode = ORB.init().create_interface_tc(id(), "IORInterceptor_3_0");
- return typeCode;
+ return OrbRestricted.Singleton.create_interface_tc(id(),
+ "IORInterceptor_3_0");
}
/**
diff --git a/org/omg/PortableInterceptor/InvalidSlotHelper.java b/org/omg/PortableInterceptor/InvalidSlotHelper.java
index 98b259677..28558a000 100644
--- a/org/omg/PortableInterceptor/InvalidSlotHelper.java
+++ b/org/omg/PortableInterceptor/InvalidSlotHelper.java
@@ -40,6 +40,7 @@ package org.omg.PortableInterceptor;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -57,22 +58,13 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class InvalidSlotHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Create the InvalidSlot typecode (structure, named "InvalidSlot").
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 0 ];
- typeCode = orb.create_exception_tc(id(), "InvalidSlot", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[0];
+ return orb.create_exception_tc(id(), "InvalidSlot", members);
}
/*
diff --git a/org/omg/PortableInterceptor/ORBInitInfoPackage/DuplicateNameHelper.java b/org/omg/PortableInterceptor/ORBInitInfoPackage/DuplicateNameHelper.java
index 648e9679b..2d9740a85 100644
--- a/org/omg/PortableInterceptor/ORBInitInfoPackage/DuplicateNameHelper.java
+++ b/org/omg/PortableInterceptor/ORBInitInfoPackage/DuplicateNameHelper.java
@@ -57,36 +57,25 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class DuplicateNameHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
- * Create the DuplicateName typecode (structure,
- * named "DuplicateName").
- * The typecode states that the structure contains the
- * following fields: name.
+ * Create the DuplicateName typecode (structure, named "DuplicateName"). The
+ * typecode states that the structure contains the following fields: name.
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 1 ];
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[1];
- TypeCode field;
+ TypeCode field;
- field = orb.get_primitive_tc(TCKind.tk_string);
- members [ 0 ] = new StructMember("name", field, null);
- typeCode = orb.create_exception_tc(id(), "DuplicateName", members);
- }
- return typeCode;
+ field = orb.get_primitive_tc(TCKind.tk_string);
+ members[0] = new StructMember("name", field, null);
+ return orb.create_exception_tc(id(), "DuplicateName", members);
}
/**
- * Insert the DuplicateName into the given Any.
- * This method uses the DuplicateNameHolder.
- *
+ * Insert the DuplicateName into the given Any. This method uses the
+ * DuplicateNameHolder.
+ *
* @param any the Any to insert into.
* @param that the DuplicateName to insert.
*/
diff --git a/org/omg/PortableInterceptor/ORBInitInfoPackage/InvalidNameHelper.java b/org/omg/PortableInterceptor/ORBInitInfoPackage/InvalidNameHelper.java
index f89f9d4c6..a87a3b747 100644
--- a/org/omg/PortableInterceptor/ORBInitInfoPackage/InvalidNameHelper.java
+++ b/org/omg/PortableInterceptor/ORBInitInfoPackage/InvalidNameHelper.java
@@ -40,6 +40,7 @@ package org.omg.PortableInterceptor.ORBInitInfoPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -58,28 +59,18 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class InvalidNameHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
- * Create the InvalidName typecode (structure,
- * named "InvalidName").
+ * Create the InvalidName typecode (structure, named "InvalidName").
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 0 ];
- typeCode = orb.create_exception_tc(id(), "InvalidName", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[0];
+ return orb.create_exception_tc(id(), "InvalidName", members);
}
/**
* Insert the InvalidName into the given Any.
- *
+ *
* @param any the Any to insert into.
* @param that the InvalidName to insert.
*/
diff --git a/org/omg/PortableInterceptor/ObjectReferenceFactoryHelper.java b/org/omg/PortableInterceptor/ObjectReferenceFactoryHelper.java
index 55ee0be18..72c864811 100644
--- a/org/omg/PortableInterceptor/ObjectReferenceFactoryHelper.java
+++ b/org/omg/PortableInterceptor/ObjectReferenceFactoryHelper.java
@@ -40,6 +40,7 @@ package org.omg.PortableInterceptor;
import gnu.CORBA.CDR.Vio;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -60,24 +61,16 @@ import org.omg.CORBA.VM_ABSTRACT;
public abstract class ObjectReferenceFactoryHelper
{
/**
- * The cached {@link ObjectReferenceFactory} typecode, computed once.
- */
- private static TypeCode typeCode;
-
- /**
* Get the type code of the {@link ObjectReferenceFactory}.
- *
- * @return value type code with the agreed id, named
- * "ObjectReferenceFactory", abstract, no members, no base type.
+ *
+ * @return value type code with the agreed id, named "ObjectReferenceFactory",
+ * abstract, no members, no base type.
*/
public static TypeCode type()
{
- if (typeCode == null)
- typeCode =
- ORB.init().create_value_tc(id(), "ObjectReferenceFactory",
- VM_ABSTRACT.value, null, new ValueMember[ 0 ]
- );
- return typeCode;
+ return OrbRestricted.Singleton.create_value_tc(id(), "ObjectReferenceFactory",
+ VM_ABSTRACT.value, null,
+ new ValueMember[0]);
}
/**
diff --git a/org/omg/PortableInterceptor/ObjectReferenceTemplateHelper.java b/org/omg/PortableInterceptor/ObjectReferenceTemplateHelper.java
index 258a73ae8..014c11308 100644
--- a/org/omg/PortableInterceptor/ObjectReferenceTemplateHelper.java
+++ b/org/omg/PortableInterceptor/ObjectReferenceTemplateHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.PortableInterceptor;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -58,24 +59,16 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class ObjectReferenceTemplateHelper
{
/**
- * The cached {@link ObjectReferenceTemplate} typecode, computed once.
- */
- private static TypeCode typeCode;
-
- /**
* Get the type code of the {@link ObjectReferenceTemplate}.
- *
- * @return value type type code, named ObjectReferenceTemplate,
- * no members, abstract.
+ *
+ * @return value type type code, named ObjectReferenceTemplate, no members,
+ * abstract.
*/
public static TypeCode type()
{
- if (typeCode == null)
- typeCode =
- ORB.init().create_value_tc(id(), "ObjectReferenceTemplate",
- VM_ABSTRACT.value, null, new ValueMember[ 0 ]
- );
- return typeCode;
+ return OrbRestricted.Singleton.create_value_tc(id(), "ObjectReferenceTemplate",
+ VM_ABSTRACT.value, null,
+ new ValueMember[0]);
}
/**
diff --git a/org/omg/PortableInterceptor/ObjectReferenceTemplateSeqHelper.java b/org/omg/PortableInterceptor/ObjectReferenceTemplateSeqHelper.java
index c4f09896f..e84f3e6be 100644
--- a/org/omg/PortableInterceptor/ObjectReferenceTemplateSeqHelper.java
+++ b/org/omg/PortableInterceptor/ObjectReferenceTemplateSeqHelper.java
@@ -57,11 +57,6 @@ import org.omg.CORBA.portable.Streamable;
public abstract class ObjectReferenceTemplateSeqHelper
{
/**
- * The type code, computed once.
- */
- static TypeCode typecode;
-
- /**
* Extract the <code>ObjectReferenceTemplate[]</code> from the given
* {@link Any}. This implementation expects the {@link Any} to hold the
* instance of {@link ObjectReferenceTemplateSeqHolder} that is returned by
@@ -142,15 +137,11 @@ public abstract class ObjectReferenceTemplateSeqHelper
*/
public static TypeCode type()
{
- if (typecode == null)
- {
- GeneralTypeCode t = new GeneralTypeCode(TCKind.tk_sequence);
- t.setId(id());
- t.setLength(0);
- t.setContentType(ObjectReferenceTemplateHelper.type());
- typecode = t;
- }
- return typecode;
+ GeneralTypeCode t = new GeneralTypeCode(TCKind.tk_sequence);
+ t.setId(id());
+ t.setLength(0);
+ t.setContentType(ObjectReferenceTemplateHelper.type());
+ return t;
}
/**
diff --git a/org/omg/PortableServer/CurrentHelper.java b/org/omg/PortableServer/CurrentHelper.java
index 281cefa6d..3afbf669b 100644
--- a/org/omg/PortableServer/CurrentHelper.java
+++ b/org/omg/PortableServer/CurrentHelper.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package org.omg.PortableServer;
+import gnu.CORBA.OrbRestricted;
+
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.NO_IMPLEMENT;
@@ -61,7 +63,7 @@ public abstract class CurrentHelper
*/
public static TypeCode type()
{
- return ORB.init().create_interface_tc(id(), "Current");
+ return OrbRestricted.Singleton.create_interface_tc(id(), "Current");
}
/**
diff --git a/org/omg/PortableServer/CurrentPackage/NoContextHelper.java b/org/omg/PortableServer/CurrentPackage/NoContextHelper.java
index 848a3c3d3..02c74c535 100644
--- a/org/omg/PortableServer/CurrentPackage/NoContextHelper.java
+++ b/org/omg/PortableServer/CurrentPackage/NoContextHelper.java
@@ -40,6 +40,7 @@ package org.omg.PortableServer.CurrentPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -58,26 +59,19 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class NoContextHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
- * Create the NoContext typecode (structure,
- * named "NoContext").
+ * Create the NoContext typecode (structure, named "NoContext").
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 0 ];
- typeCode = orb.create_exception_tc(id(), "NoContext", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[0];
+ return orb.create_exception_tc(id(), "NoContext", members);
}
- /* Every user exception with no user defined fields can use EmptyExceptionHolder */
+ /*
+ * Every user exception with no user defined fields can use
+ * EmptyExceptionHolder
+ */
/**
* Insert the NoContext into the given Any.
diff --git a/org/omg/PortableServer/ForwardRequestHelper.java b/org/omg/PortableServer/ForwardRequestHelper.java
index f4b0619b0..b30a2abeb 100644
--- a/org/omg/PortableServer/ForwardRequestHelper.java
+++ b/org/omg/PortableServer/ForwardRequestHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.PortableServer;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import gnu.CORBA.Poa.ForwardRequestHolder;
import org.omg.CORBA.Any;
@@ -62,11 +63,6 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class ForwardRequestHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Extract the ForwardRequest from given Any.
* This method uses the ForwardRequestHolder.
*
@@ -132,18 +128,14 @@ public abstract class ForwardRequestHelper
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
StructMember[] members = new StructMember[ 1 ];
TypeCode field;
field = ObjectHelper.type();
members [ 0 ] = new StructMember("forward_reference", field, null);
- typeCode = orb.create_exception_tc(id(), "ForwardRequest", members);
- }
- return typeCode;
+ return orb.create_exception_tc(id(), "ForwardRequest", members);
}
/**
diff --git a/org/omg/PortableServer/POAHelper.java b/org/omg/PortableServer/POAHelper.java
index 3712da00d..d6a951be5 100644
--- a/org/omg/PortableServer/POAHelper.java
+++ b/org/omg/PortableServer/POAHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.PortableServer;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.TypeCode;
@@ -80,7 +81,7 @@ public abstract class POAHelper
*/
public static TypeCode type()
{
- return ORB.init().create_interface_tc(id(), "POA");
+ return OrbRestricted.Singleton.create_interface_tc(id(), "POA");
}
/**
diff --git a/org/omg/PortableServer/POAManagerPackage/AdapterInactiveHelper.java b/org/omg/PortableServer/POAManagerPackage/AdapterInactiveHelper.java
index 2a587a412..e23d11997 100644
--- a/org/omg/PortableServer/POAManagerPackage/AdapterInactiveHelper.java
+++ b/org/omg/PortableServer/POAManagerPackage/AdapterInactiveHelper.java
@@ -40,6 +40,7 @@ package org.omg.PortableServer.POAManagerPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -58,23 +59,14 @@ import org.omg.CORBA.portable.OutputStream;
public abstract class AdapterInactiveHelper
{
/**
- * The cached typecode value, computed only once.
- */
- private static TypeCode typeCode;
-
- /**
* Create the AdapterInactive typecode (structure,
* named "AdapterInactive").
*/
public static TypeCode type()
{
- if (typeCode == null)
- {
- ORB orb = ORB.init();
- StructMember[] members = new StructMember[ 0 ];
- typeCode = orb.create_exception_tc(id(), "AdapterInactive", members);
- }
- return typeCode;
+ ORB orb = OrbRestricted.Singleton;
+ StructMember[] members = new StructMember[ 0 ];
+ return orb.create_exception_tc(id(), "AdapterInactive", members);
}
/* Every user exception with no user defined
diff --git a/org/omg/PortableServer/POAPackage/AdapterAlreadyExistsHelper.java b/org/omg/PortableServer/POAPackage/AdapterAlreadyExistsHelper.java
index 61a410891..f616637ae 100644
--- a/org/omg/PortableServer/POAPackage/AdapterAlreadyExistsHelper.java
+++ b/org/omg/PortableServer/POAPackage/AdapterAlreadyExistsHelper.java
@@ -40,6 +40,7 @@ package org.omg.PortableServer.POAPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -70,7 +71,7 @@ public abstract class AdapterAlreadyExistsHelper
{
if (typeCode == null)
{
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
StructMember[] members = new StructMember[ 0 ];
typeCode =
orb.create_exception_tc(id(), "AdapterAlreadyExists", members);
diff --git a/org/omg/PortableServer/POAPackage/AdapterNonExistentHelper.java b/org/omg/PortableServer/POAPackage/AdapterNonExistentHelper.java
index dd318bf09..bad920a5a 100644
--- a/org/omg/PortableServer/POAPackage/AdapterNonExistentHelper.java
+++ b/org/omg/PortableServer/POAPackage/AdapterNonExistentHelper.java
@@ -40,6 +40,7 @@ package org.omg.PortableServer.POAPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -70,7 +71,7 @@ public abstract class AdapterNonExistentHelper
{
if (typeCode == null)
{
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
StructMember[] members = new StructMember[ 0 ];
typeCode = orb.create_exception_tc(id(), "AdapterNonExistent", members);
}
diff --git a/org/omg/PortableServer/POAPackage/InvalidPolicyHelper.java b/org/omg/PortableServer/POAPackage/InvalidPolicyHelper.java
index 5e9e627c7..32ddae858 100644
--- a/org/omg/PortableServer/POAPackage/InvalidPolicyHelper.java
+++ b/org/omg/PortableServer/POAPackage/InvalidPolicyHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.PortableServer.POAPackage;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import gnu.CORBA.Poa.InvalidPolicyHolder;
import org.omg.CORBA.Any;
@@ -72,7 +73,7 @@ public abstract class InvalidPolicyHelper
{
if (typeCode == null)
{
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
StructMember[] members = new StructMember[ 1 ];
TypeCode field;
diff --git a/org/omg/PortableServer/POAPackage/NoServantHelper.java b/org/omg/PortableServer/POAPackage/NoServantHelper.java
index fd2c189fc..b9afb8ed7 100644
--- a/org/omg/PortableServer/POAPackage/NoServantHelper.java
+++ b/org/omg/PortableServer/POAPackage/NoServantHelper.java
@@ -40,6 +40,7 @@ package org.omg.PortableServer.POAPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -70,7 +71,7 @@ public abstract class NoServantHelper
{
if (typeCode == null)
{
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
StructMember[] members = new StructMember[ 0 ];
typeCode = orb.create_exception_tc(id(), "NoServant", members);
}
diff --git a/org/omg/PortableServer/POAPackage/ObjectAlreadyActiveHelper.java b/org/omg/PortableServer/POAPackage/ObjectAlreadyActiveHelper.java
index 011867473..bf5e9cd9e 100644
--- a/org/omg/PortableServer/POAPackage/ObjectAlreadyActiveHelper.java
+++ b/org/omg/PortableServer/POAPackage/ObjectAlreadyActiveHelper.java
@@ -40,6 +40,7 @@ package org.omg.PortableServer.POAPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -70,7 +71,7 @@ public abstract class ObjectAlreadyActiveHelper
{
if (typeCode == null)
{
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
StructMember[] members = new StructMember[ 0 ];
typeCode =
orb.create_exception_tc(id(), "ObjectAlreadyActive", members);
diff --git a/org/omg/PortableServer/POAPackage/ObjectNotActiveHelper.java b/org/omg/PortableServer/POAPackage/ObjectNotActiveHelper.java
index 0d8ff473c..2f5867cbd 100644
--- a/org/omg/PortableServer/POAPackage/ObjectNotActiveHelper.java
+++ b/org/omg/PortableServer/POAPackage/ObjectNotActiveHelper.java
@@ -40,6 +40,7 @@ package org.omg.PortableServer.POAPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -70,7 +71,7 @@ public abstract class ObjectNotActiveHelper
{
if (typeCode == null)
{
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
StructMember[] members = new StructMember[ 0 ];
typeCode = orb.create_exception_tc(id(), "ObjectNotActive", members);
}
diff --git a/org/omg/PortableServer/POAPackage/ServantAlreadyActiveHelper.java b/org/omg/PortableServer/POAPackage/ServantAlreadyActiveHelper.java
index a74e67401..33ca06674 100644
--- a/org/omg/PortableServer/POAPackage/ServantAlreadyActiveHelper.java
+++ b/org/omg/PortableServer/POAPackage/ServantAlreadyActiveHelper.java
@@ -40,6 +40,7 @@ package org.omg.PortableServer.POAPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -70,7 +71,7 @@ public abstract class ServantAlreadyActiveHelper
{
if (typeCode == null)
{
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
StructMember[] members = new StructMember[ 0 ];
typeCode =
orb.create_exception_tc(id(), "ServantAlreadyActive", members);
diff --git a/org/omg/PortableServer/POAPackage/ServantNotActiveHelper.java b/org/omg/PortableServer/POAPackage/ServantNotActiveHelper.java
index 5fb52cf35..e86f4e948 100644
--- a/org/omg/PortableServer/POAPackage/ServantNotActiveHelper.java
+++ b/org/omg/PortableServer/POAPackage/ServantNotActiveHelper.java
@@ -40,6 +40,7 @@ package org.omg.PortableServer.POAPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -70,7 +71,7 @@ public abstract class ServantNotActiveHelper
{
if (typeCode == null)
{
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
StructMember[] members = new StructMember[ 0 ];
typeCode = orb.create_exception_tc(id(), "ServantNotActive", members);
}
diff --git a/org/omg/PortableServer/POAPackage/WrongAdapterHelper.java b/org/omg/PortableServer/POAPackage/WrongAdapterHelper.java
index cd862b081..7650014c1 100644
--- a/org/omg/PortableServer/POAPackage/WrongAdapterHelper.java
+++ b/org/omg/PortableServer/POAPackage/WrongAdapterHelper.java
@@ -40,6 +40,7 @@ package org.omg.PortableServer.POAPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -70,7 +71,7 @@ public abstract class WrongAdapterHelper
{
if (typeCode == null)
{
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
StructMember[] members = new StructMember[ 0 ];
typeCode = orb.create_exception_tc(id(), "WrongAdapter", members);
}
diff --git a/org/omg/PortableServer/POAPackage/WrongPolicyHelper.java b/org/omg/PortableServer/POAPackage/WrongPolicyHelper.java
index a1f27cbb0..a9e7fc594 100644
--- a/org/omg/PortableServer/POAPackage/WrongPolicyHelper.java
+++ b/org/omg/PortableServer/POAPackage/WrongPolicyHelper.java
@@ -40,6 +40,7 @@ package org.omg.PortableServer.POAPackage;
import gnu.CORBA.EmptyExceptionHolder;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -70,7 +71,7 @@ public abstract class WrongPolicyHelper
{
if (typeCode == null)
{
- ORB orb = ORB.init();
+ ORB orb = OrbRestricted.Singleton;
StructMember[] members = new StructMember[ 0 ];
typeCode = orb.create_exception_tc(id(), "WrongPolicy", members);
}
diff --git a/org/omg/PortableServer/ServantActivatorHelper.java b/org/omg/PortableServer/ServantActivatorHelper.java
index 8aa58b2f6..e1c4f09c8 100644
--- a/org/omg/PortableServer/ServantActivatorHelper.java
+++ b/org/omg/PortableServer/ServantActivatorHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.PortableServer;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -61,7 +62,7 @@ public abstract class ServantActivatorHelper
*/
public static TypeCode type()
{
- return ORB.init().create_interface_tc(id(), "ServantActivator");
+ return OrbRestricted.Singleton.create_interface_tc(id(), "ServantActivator");
}
/**
diff --git a/org/omg/PortableServer/ServantLocatorHelper.java b/org/omg/PortableServer/ServantLocatorHelper.java
index 082c4c586..7bb933f7b 100644
--- a/org/omg/PortableServer/ServantLocatorHelper.java
+++ b/org/omg/PortableServer/ServantLocatorHelper.java
@@ -39,6 +39,7 @@ exception statement from your version. */
package org.omg.PortableServer;
import gnu.CORBA.Minor;
+import gnu.CORBA.OrbRestricted;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_OPERATION;
@@ -60,7 +61,7 @@ public abstract class ServantLocatorHelper
*/
public static TypeCode type()
{
- return ORB.init().create_interface_tc(id(), "ServantLocator");
+ return OrbRestricted.Singleton.create_interface_tc(id(), "ServantLocator");
}
/**
diff --git a/resource/META-INF/services/.cvsignore b/resource/META-INF/services/.cvsignore
new file mode 100644
index 000000000..00abb1c13
--- /dev/null
+++ b/resource/META-INF/services/.cvsignore
@@ -0,0 +1 @@
+java.util.prefs.PreferencesFactory
diff --git a/resource/META-INF/services/javax.sound.sampled.spi.AudioFileReader b/resource/META-INF/services/javax.sound.sampled.spi.AudioFileReader
new file mode 100644
index 000000000..4fd59badb
--- /dev/null
+++ b/resource/META-INF/services/javax.sound.sampled.spi.AudioFileReader
@@ -0,0 +1,2 @@
+gnu.javax.sound.sampled.WAV.WAVReader
+gnu.javax.sound.sampled.AU.AUReader
diff --git a/resource/gnu/classpath/tools/jarsigner/messages.properties b/resource/gnu/classpath/tools/jarsigner/messages.properties
index 4383256de..d4088177c 100644
--- a/resource/gnu/classpath/tools/jarsigner/messages.properties
+++ b/resource/gnu/classpath/tools/jarsigner/messages.properties
@@ -119,4 +119,8 @@ SFHelper.1=Helper is NOT finished
SFHelper.4=.SF file has NOT been generated
SFHelper.6=Unknown or unsupported private key algorithm
SFHelper.9=Helper is NOT ready
+SFHelper.0=Warning: The certificate issued by {0}, for {1}, has expired as of {3,date,full} - {3,time,full}.
SFHelper.10=Helper is NOT started
+SFHelper.11=Warning: The certificate issued by {0}, for {1}, is only valid after {3,date,full} - {3,time,full}.
+SFHelper.14=[unknown]
+SFHelper.17=[unnamed]
diff --git a/resource/gnu/java/awt/peer/x/fonts.properties b/resource/gnu/java/awt/peer/x/fonts.properties
new file mode 100644
index 000000000..71a95c193
--- /dev/null
+++ b/resource/gnu/java/awt/peer/x/fonts.properties
@@ -0,0 +1,61 @@
+# fonts.properties
+# 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.
+
+serif.plain=-adobe-times-medium-r-normal--*-%d-75-*-p-*-iso8859-1
+serif.bold=-adobe-times-bold-r-normal--*-%d-75-*-p-*-iso8859-1
+serif.italic=-adobe-times-medium-o-normal--*-%d-75-*-p-*-iso8859-1
+serif.bolditalic=-adobe-times-bold-o-normal--*-%d-75-*-p-*-iso8859-1
+
+sansserif.plain=-adobe-helvetica-medium-r-normal--*-%d-75-*-p-*-iso8859-1
+sansserif.bold=-adobe-helvetica-bold-r-normal--*-%d-75-*-p-*-iso8859-1
+sansserif.italic=-adobe-helvetica-medium-o-normal--*-%d-75-*-p-*-iso8859-1
+sansserif.bolditalic=-adobe-helvetica-bold-o-normal--*-%d-75-*-p-*-iso8859-1
+
+monospaced.plain=-adobe-courier-medium-r-normal--*-%d-75-*-p-*-iso8859-1
+monospaced.bold=-adobe-courier-bold-r-normal--*-%d-75-*-p-*-iso8859-1
+monospaced.italic=-adobe-courier-medium-o-normal--*-%d-75-*-p-*-iso8859-1
+monospaced.bolditalic=-adobe-courier-bold-o-normal--*-%d-75-*-p-*-iso8859-1
+
+dialog.plain=-adobe-helvetica-medium-r-normal--*-%d-75-*-p-*-iso8859-1
+dialog.bold=-adobe-helvetica-bold-r-normal--*-%d-75-*-p-*-iso8859-1
+dialog.italic=-adobe-helvetica-medium-o-normal--*-%d-75-*-p-*-iso8859-1
+dialog.bolditalic=-adobe-helvetica-bold-o-normal--*-%d-75-*-p-*-iso8859-1
+
+dialoginput.plain=-adobe-helvetica-medium-r-normal--*-%d-75-*-p-*-iso8859-1
+dialoginput.bold=-adobe-helvetica-bold-r-normal--*-%d-75-*-p-*-iso8859-1
+dialoginput.italic=-adobe-helvetica-medium-o-normal--*-%d-75-*-p-*-iso8859-1
+dialoginput.bolditalic=-adobe-helvetica-bold-o-normal--*-%d-75-*-p-*-iso8859-1
diff --git a/resource/gnu/java/util/regex/MessagesBundle.properties b/resource/gnu/java/util/regex/MessagesBundle.properties
new file mode 100644
index 000000000..fb2f27c39
--- /dev/null
+++ b/resource/gnu/java/util/regex/MessagesBundle.properties
@@ -0,0 +1,22 @@
+# Localized error messages for gnu.regexp
+
+# Prefix for REException messages
+error.prefix=At position {0} in regular expression pattern:
+
+# REException (parse error) messages
+repeat.assertion=repeated token is zero-width assertion
+repeat.chained=attempted to repeat a token that is already repeated
+repeat.no.token=quantifier (?*+{}) without preceding token
+repeat.empty.token=repeated token may be empty
+unmatched.brace=unmatched brace
+unmatched.bracket=unmatched bracket
+unmatched.paren=unmatched parenthesis
+interval.no.end=unexpected end of interval
+class.no.end=unexpected end of character class
+subexpr.no.end=unexpected end of subexpression
+interval.order=an interval''s minimum is greater than its maximum
+interval.error=an interval is empty * or contains illegal characters
+ends.with.backslash=backslash at end of pattern
+
+# RESyntax message
+syntax.final=Syntax has been declared final and cannot be modified
diff --git a/resource/gnu/java/util/regex/MessagesBundle_fr.properties b/resource/gnu/java/util/regex/MessagesBundle_fr.properties
new file mode 100644
index 000000000..99da4e22d
--- /dev/null
+++ b/resource/gnu/java/util/regex/MessagesBundle_fr.properties
@@ -0,0 +1,22 @@
+# Localized error messages for gnu.regexp
+
+# Prefix for REException messages
+error.prefix=A l''index {0} dans le modèle d''expression régulière:
+
+# REException (parse error) messages
+repeat.assertion=l''élément répété est de largeur zéro
+repeat.chained=tentative de répétition d''un élément déjà répété
+repeat.no.token=quantifieur (?*+{}) sans élément précédent
+repeat.empty.token=l''élément répété peut être vide
+unmatched.brace=accolade inégalée
+unmatched.bracket=crochet inégalé
+unmatched.paren=parenthèse inégalée
+interval.no.end=fin d''interval non attendue
+class.no.end=fin de classe de caractères non attendue
+subexpr.no.end=fin de sous-expression non attendue
+interval.order=l''interval minimum est supérieur à l''interval maximum
+interval.error=l''interval est vide ou contient des caractères illégaux
+ends.with.backslash=antislash à la fin du modèle
+
+# RESyntax message
+syntax.final=La syntaxe a été déclarée finale et ne peut pas être modifiée
diff --git a/resource/gnu/java/util/regex/MessagesBundle_it.properties b/resource/gnu/java/util/regex/MessagesBundle_it.properties
new file mode 100644
index 000000000..bee7be5a7
--- /dev/null
+++ b/resource/gnu/java/util/regex/MessagesBundle_it.properties
@@ -0,0 +1,31 @@
+# Localized error messages for gnu.regexp, in Italian.
+# $Id: MessagesBundle_it.properties,v 1.1.6.1 2006-08-14 09:41:27 glavaux Exp $
+# Messaggi italiani per gnu.regexp.
+#
+# Attenzione: Questa traduzione fu scritto da un italo-americano.
+# Per favore correggete l'italiano bestemmiato e mandate i patch
+# al listo <classpath at gnu dot org>.
+#
+# @author Steven Augart <steve at watson dot ibm dot com>, <steve at augart dot com>
+
+# Prefix for REException messages
+error.prefix=Al indice {0} nel modello dell''espressione regulare:
+
+# REException (parse error) messages
+repeat.assertion=l''elemento ripetuto ha larghezza zero
+repeat.chained=prova di ripetere un elemento già ripetuto
+repeat.no.token=quantificatore (?*+{}) senza elemento precedente
+repeat.empty.token=l''elemento ripetuto può essere vuoto
+unmatched.brace=parentesi quadra senza corrispondente
+unmatched.bracket=graffa senza corrispondente
+unmatched.paren=parentesi senza corrispondente
+interval.no.end=la fine d''intervallo è imprevista
+class.no.end=la fine della classe di caratteri è imprevista
+subexpr.no.end=la fine del sub-espressione è imprevista
+interval.order=il valore minimo d''intervallo è piú grande del suo valore massimo
+interval.error=l''intervallo è vuoto o contiene caratteri impermessibili
+# Non so come si dice "backslash" in italiano.
+ends.with.backslash=il modello finisce con un backslash (il carattere "\")
+
+# RESyntax message
+syntax.final=La sintassi è dichiarata "final" (finale) e non si può modificarla
diff --git a/resource/java/security/classpath.security b/resource/java/security/classpath.security
index 13d691bfe..166ac2ee2 100644
--- a/resource/java/security/classpath.security
+++ b/resource/java/security/classpath.security
@@ -1,5 +1,5 @@
# classpath.security
-# Copyright (C) 2002 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2006 Free Software Foundation, Inc.
#
# This file is part of GNU Classpath.
#
@@ -41,3 +41,11 @@ security.provider.2=gnu.javax.crypto.jce.GnuCrypto
security.provider.3=gnu.javax.crypto.jce.GnuSasl
security.provider.4=gnu.javax.net.ssl.provider.Jessie
security.provider.5=gnu.javax.security.auth.callback.GnuCallbacks
+
+# The VM-wide default callback handler class name. MUST be a subclass of
+# javax.security.auth.callback.CallbackHandler
+auth.login.defaultCallbackHandler=gnu.javax.security.auth.callback.DefaultCallbackHandler
+
+# If this file isn't found we fall back to generating entropy through
+# "battling threads".
+securerandom.source=file:///dev/urandom
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index a08616618..433784018 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -1,2 +1,2 @@
-EXTRA_DIST = check_jni_methods.sh generate-locale-list.sh
+EXTRA_DIST = check_jni_methods.sh generate-locale-list.sh import-cacerts.sh
diff --git a/scripts/import-cacerts.sh b/scripts/import-cacerts.sh
new file mode 100755
index 000000000..993d58474
--- /dev/null
+++ b/scripts/import-cacerts.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+function visitFile() {
+ install/bin/gkeytool \
+ -cacert \
+ -v \
+ -storepass changeit \
+ -keystore resource/java/security/cacerts.gkr \
+ -file "$1"
+}
+
+function visitDir() {
+ local d
+ d=$1
+ for f in "$d/"*
+ do
+ if [ -d "$f" ] ; then
+ visitDir "$f"
+ else
+ visitFile "$f"
+ fi
+ done
+}
+
+if [ "$#" -lt "1" ] ; then
+ echo "Usage: import-cacerts DIR"
+ echo "Import CA trusted certificates into a 'cacerts.gkr' key store"
+ echo "under resource/java/security using 'changeit' as its password,"
+ echo "and constructing the Alias from the certificate's file name."
+ echo
+ echo " DIR the 'ca-certificates' deb package installation directory"
+ echo " containing trusted CA certificates."
+ echo
+else
+ caDir=$1
+ if [ ! -d $caDir ] ; then
+ echo "Argument MUST be a directory."
+ echo "Type command with no arguments for usage string."
+ exit 1
+ fi
+ visitDir $caDir
+fi
+exit 0 \ No newline at end of file
diff --git a/tools/.cvsignore b/tools/.cvsignore
index d2e24c413..49dfefd00 100644
--- a/tools/.cvsignore
+++ b/tools/.cvsignore
@@ -8,3 +8,7 @@ appletviewer
gappletviewer
gjarsigner
gkeytool
+gjar
+gnative2ascii
+gserialver
+gjavah
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 2204daef3..2f417e69a 100755
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,6 +1,6 @@
## Input file for automake to generate the Makefile.in used by configure
-GLIBJ_CLASSPATH='$(top_builddir)/lib':'$(top_builddir)/lib/glibj.zip'
+GLIBJ_CLASSPATH='$(top_builddir)/lib':'$(top_builddir)/lib/glibj.zip':$(PATH_TO_ASM)
# Setup the compiler to use the GNU Classpath library we just build
if FOUND_GCJ
@@ -13,7 +13,7 @@ if FOUND_GCJX
JCOMPILER = $(GCJX) -encoding UTF-8 -bootclasspath '' -sourcepath '' -classpath $(GLIBJ_CLASSPATH):.
else
if FOUND_ECJ
-JCOMPILER = $(ECJ) -encoding UTF-8 -bootclasspath $(GLIBJ_CLASSPATH) -classpath .
+JCOMPILER = $(ECJ) -source 1.4 -encoding UTF-8 -bootclasspath $(GLIBJ_CLASSPATH) -classpath .
else
error dunno how to setup the JCOMPILER and compile
endif
@@ -21,10 +21,14 @@ endif
endif
endif
+if USE_ASM
+javah = gjavah
+endif
+
if CREATE_WRAPPERS
bin_SCRIPTS =
bin_PROGRAMS = gappletviewer gjarsigner gkeytool \
- gjar gnative2ascii gserialver
+ gjar gnative2ascii gserialver $(javah)
if FOUND_GCJ
LIBJVM = -lgcj
@@ -76,13 +80,21 @@ gserialver_CFLAGS = \
-DTOOLNAME="\"gserialver\""
gserialver_LDFLAGS = -L$(libdir) $(LIBJVM)
+if USE_ASM
+gjavah_SOURCES = toolwrapper.c
+gjavah_CFLAGS = \
+ -DTOOLPACKAGE="\"javah\"" \
+ -DTOOLNAME="\"gjavah\""
+gjavah_LDFLAGS = -L$(libdir) $(LIBJVM)
+endif
+
else
bin_SCRIPTS = gappletviewer gjarsigner gkeytool \
- gjar gnative2ascii gserialver
+ gjar gnative2ascii gserialver $(javah)
bin_PROGRAMS =
endif
EXTRA_DIST = toolwrapper.c gappletviewer.in gjarsigner.in gkeytool.in \
- gjar.in gnative2ascii.in gserialver.in
+ gjar.in gnative2ascii.in gserialver.in gjavah.in
# All our example java source files
TOOLS_JAVA_FILES = $(srcdir)/gnu/classpath/tools/*.java $(srcdir)/gnu/classpath/tools/*/*.java $(srcdir)/gnu/classpath/tools/*/*/*.java
@@ -145,12 +157,18 @@ $(TOOLS_ZIP): $(TOOLS_JAVA_FILES)
cp $(GRMIC_TEMPLATES) classes/gnu/classpath/tools/giop/grmic/templates
cp $(RMI_HELPS) classes/gnu/classpath/tools/rmi/
cp $(GIOP_HELPS) classes/gnu/classpath/tools/giop/
- $(JCOMPILER) -d classes $(TOOLS_JAVA_FILES)
+ find $(srcdir)/gnu/classpath/tools -name '*.java' -print > classes.lst
+ if test -z "$(PATH_TO_ASM)"; then \
+ mv classes.lst classes.tmp; \
+ fgrep -v /javah/ classes.tmp > classes.lst; \
+ rm -f classes.tmp;\
+ fi
+ $(JCOMPILER) -d classes @classes.lst
(cd classes; \
if test "$(ZIP)" != ""; then $(ZIP) -r ../$(TOOLS_ZIP) .; fi; \
if test "$(FASTJAR)" != ""; then $(FASTJAR) cf ../$(TOOLS_ZIP) .; fi; \
cd ..)
- rm -rf classes
+ rm -rf classes classes.lst
# Zip file be gone! (and make sure the classes are gone too)
clean-local:
diff --git a/tools/gjavah.in b/tools/gjavah.in
new file mode 100644
index 000000000..0505bdbc2
--- /dev/null
+++ b/tools/gjavah.in
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+## Copyright (C) 2006 Free Software Foundation, Inc.
+##
+## This file is a part of GNU Classpath.
+##
+## GNU Classpath is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or (at
+## your option) any later version.
+##
+## GNU Classpath is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with GNU Classpath; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+## USA.
+##
+## Linking this library statically or dynamically with other modules is
+## making a combined work based on this library. Thus, the terms and
+## conditions of the GNU General Public License cover the whole
+## combination.
+##
+## As a special exception, the copyright holders of this library give you
+## permission to link this library with independent modules to produce an
+## executable, regardless of the license terms of these independent
+## modules, and to copy and distribute the resulting executable under
+## terms of your choice, provided that you also meet, for each linked
+## independent module, the terms and conditions of the license of that
+## module. An independent module is a module which is not derived from
+## or based on this library. If you modify this library, you may extend
+## this exception to your version of the library, but you are not
+## obligated to do so. If you do not wish to do so, delete this
+## exception statement from your version.
+##
+##
+## A simple shell script to launch the GNU Classpath javah tool.
+##
+
+prefix=@prefix@
+tools_dir=@datadir@/@PACKAGE@
+tools_cp=${tools_dir}/tools.zip:@PATH_TO_ASM@
+
+exec @VM_BINARY@ -Xbootclasspath/p:"${tools_cp}" gnu.classpath.tools.javah.Main "$@"
diff --git a/tools/gnu/classpath/tools/jarsigner/SFHelper.java b/tools/gnu/classpath/tools/jarsigner/SFHelper.java
index 0d8c2eb44..83e87b843 100644
--- a/tools/gnu/classpath/tools/jarsigner/SFHelper.java
+++ b/tools/gnu/classpath/tools/jarsigner/SFHelper.java
@@ -63,10 +63,13 @@ import java.security.PrivateKey;
import java.security.cert.CRLException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509CRL;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.RSAPrivateKey;
import java.util.ArrayList;
+import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -265,6 +268,30 @@ public class SFHelper
Set signerInfos = new HashSet();
X509Certificate cert = (X509Certificate) certificates[0];
+ try
+ {
+ cert.checkValidity();
+ }
+ catch (CertificateExpiredException x)
+ {
+ String issuerName = getIssuerName(cert);
+ String subjectName = getSubjectName(cert);
+ Date notAfterDate = getNotAfterDate(cert);
+ System.out.println(Messages.getFormattedString("SFHelper.0", //$NON-NLS-1$
+ new Object[] { issuerName,
+ subjectName,
+ notAfterDate }));
+ }
+ catch (CertificateNotYetValidException x)
+ {
+ String issuerName = getIssuerName(cert);
+ String subjectName = getSubjectName(cert);
+ Date notBeforeDate = getNotBeforeDate(cert);
+ System.out.println(Messages.getFormattedString("SFHelper.11", //$NON-NLS-1$
+ new Object[] { issuerName,
+ subjectName,
+ notBeforeDate }));
+ }
X500Principal issuer = cert.getIssuerX500Principal();
BigInteger serialNumber = cert.getSerialNumber();
byte[] authenticatedAttributes = null;
@@ -379,4 +406,100 @@ public class SFHelper
this.state = FINISHED;
}
+
+ /**
+ * Given an X.509 certificate this method returns the string representation of
+ * the Issuer Distinguished Name.
+ *
+ * @param cert an X.509 certificate.
+ * @return the string representation of the Issuer's DN.
+ */
+ private String getIssuerName(X509Certificate cert)
+ {
+ X500Principal xp = cert.getIssuerX500Principal();
+ if (xp == null)
+ {
+ if (Configuration.DEBUG)
+ log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$
+ + ", has null Issuer. Return [unknown]"); //$NON-NLS-1$
+ return Messages.getString("SFHelper.14"); //$NON-NLS-1$
+ }
+ String result = xp.getName();
+ if (result == null)
+ {
+ if (Configuration.DEBUG)
+ log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$
+ + ", has an Issuer with null DN. Return [unnamed]"); //$NON-NLS-1$
+ return Messages.getString("SFHelper.17"); //$NON-NLS-1$
+ }
+ return result;
+ }
+
+ /**
+ * Given an X.509 certificate this method returns the string representation of
+ * the Subject Distinguished Name.
+ *
+ * @param cert an X.509 certificate.
+ * @return the string representation of the Subject's DN.
+ */
+ private String getSubjectName(X509Certificate cert)
+ {
+ X500Principal xp = cert.getSubjectX500Principal();
+ if (xp == null)
+ {
+ if (Configuration.DEBUG)
+ log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$
+ + ", has null Subject. Return [unknown]"); //$NON-NLS-1$
+ return Messages.getString("SFHelper.14"); //$NON-NLS-1$
+ }
+ String result = xp.getName();
+ if (result == null)
+ {
+ if (Configuration.DEBUG)
+ log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$
+ + ", has a Subject with null DN. Return [unnamed]"); //$NON-NLS-1$
+ return Messages.getString("SFHelper.17"); //$NON-NLS-1$
+ }
+ return result;
+ }
+
+ /**
+ * Given an X.509 certificate this method returns the end validity date of
+ * this certificate.
+ *
+ * @param cert an X.509 certificate.
+ * @return the date when this certificate stops being valid.
+ */
+ private Date getNotAfterDate(X509Certificate cert)
+ {
+ Date result = cert.getNotAfter();
+ if (result == null)
+ {
+ if (Configuration.DEBUG)
+ log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$
+ + ", has null start-validity date. Return epoch"); //$NON-NLS-1$
+ return new Date(0);
+ }
+ return result;
+ }
+
+ /**
+ * Given an X.509 certificate this method returns the start validity date of
+ * this certificate.
+ *
+ * @param cert an X.509 certificate.
+ * @return the date when this certificate starts being valid.
+ */
+ private Date getNotBeforeDate(X509Certificate cert)
+ {
+ Date result = cert.getNotBefore();
+ if (result == null)
+ {
+ if (Configuration.DEBUG)
+ log.fine("Certiticate, with serial number " + cert.getSerialNumber() //$NON-NLS-1$
+ + ", has null end-validity date. Return epoch"); //$NON-NLS-1$
+ return new Date(0);
+ }
+ return result;
+ }
}
diff --git a/tools/gnu/classpath/tools/javah/ClassWrapper.java b/tools/gnu/classpath/tools/javah/ClassWrapper.java
new file mode 100644
index 000000000..778896395
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/ClassWrapper.java
@@ -0,0 +1,341 @@
+/* ClassWrapper.java - wrap ASM class objects
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+public class ClassWrapper
+ extends ClassNode
+{
+ Main classpath;
+
+ ClassWrapper superClass;
+
+ ArrayList interfaceClasses;
+
+ // The virtual table for this class.
+ ArrayList vtable;
+
+ // A set of all the bridge method targets we've found.
+ HashSet bridgeTargets;
+
+ // A set of all the method names in this class.
+ HashSet methodNames = new HashSet();
+
+ public ClassWrapper(Main classpath)
+ {
+ this.classpath = classpath;
+ }
+
+ public boolean hasNativeMethod()
+ {
+ Iterator i = methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode method = (MethodNode) i.next();
+ if (Modifier.isNative(method.access))
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isThrowable() throws IOException
+ {
+ linkSupers();
+ ClassWrapper self = this;
+ while (self != null)
+ {
+ if (self.name.equals("java/lang/Throwable"))
+ return true;
+ self = self.superClass;
+ }
+ return false;
+ }
+
+ private void linkSupers() throws IOException
+ {
+ if (superName == null)
+ {
+ // Object, do nothing.
+ return;
+ }
+ if (superClass == null)
+ {
+ superClass = classpath.getClass(superName);
+ assert interfaceClasses == null;
+ interfaceClasses = new ArrayList();
+ for (int i = 0; i < interfaces.size(); ++i)
+ {
+ String ifname = (String) interfaces.get(i);
+ ClassWrapper iface = classpath.getClass(ifname);
+ iface.linkSupers();
+ interfaceClasses.add(iface);
+ }
+ }
+ superClass.linkSupers();
+ }
+
+ private int findSlot(MethodNode method)
+ {
+ for (int i = vtable.size() - 1; i >= 0; --i)
+ {
+ MethodNode base = (MethodNode) vtable.get(i);
+ if (MethodHelper.overrides(method, base))
+ return i;
+ }
+ return - 1;
+ }
+
+ private void addInterfaceMethods(ClassWrapper iface)
+ {
+ Iterator i = iface.methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode im = (MethodNode) i.next();
+ int slot = findSlot(im);
+ if (slot == - 1)
+ {
+ vtable.add(im);
+ // Also add it to our local methods.
+ methods.add(im);
+ }
+ }
+ addInterfaces(iface);
+ }
+
+ private void addInterfaces(ClassWrapper base)
+ {
+ if (base.interfaceClasses == null)
+ return;
+ Iterator i = base.interfaceClasses.iterator();
+ while (i.hasNext())
+ {
+ ClassWrapper iface = (ClassWrapper) i.next();
+ addInterfaceMethods(iface);
+ }
+ }
+
+ private void addLocalMethods()
+ {
+ Iterator i = methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode meth = (MethodNode) i.next();
+ methodNames.add(meth.name);
+ if (Modifier.isStatic(meth.access))
+ continue;
+ int slot = findSlot(meth);
+ if (slot == - 1)
+ vtable.add(meth);
+ else
+ vtable.set(slot, meth);
+ }
+ }
+
+ private void makeVtable() throws IOException
+ {
+ if (vtable != null)
+ return;
+ if (superClass != null)
+ {
+ superClass.makeVtable();
+ vtable = new ArrayList(superClass.vtable);
+ bridgeTargets = new HashSet(superClass.bridgeTargets);
+ }
+ else
+ {
+ // Object.
+ vtable = new ArrayList();
+ bridgeTargets = new HashSet();
+ }
+ addLocalMethods();
+ addInterfaces(this);
+
+ // Make a set of all the targets of bridge methods.
+ // We rename bridge methods to avoid problems with C++.
+ Iterator i = methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode m = (MethodNode) i.next();
+ String desc = MethodHelper.getBridgeTarget(m);
+ if (desc != null)
+ bridgeTargets.add(m.name + desc);
+ }
+ }
+
+ private void printFields(CniPrintStream out)
+ {
+ Iterator i = fields.iterator();
+ ClassWrapper self = superClass;
+ while (i.hasNext())
+ {
+ FieldNode f = (FieldNode) i.next();
+ boolean hasMethodName = methodNames.contains(f.name);
+ if (FieldHelper.print(out, f, self, hasMethodName))
+ self = null;
+ }
+ }
+
+ private void printMethods(CniPrintStream out) throws IOException
+ {
+ makeVtable();
+
+ // A given method is either static, overrides a super method, or
+ // is already in vtable order.
+ Iterator i = methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode m = (MethodNode) i.next();
+ boolean isTarget = bridgeTargets.contains(m.name + m.desc);
+ MethodHelper.print(out, m, this, isTarget);
+ }
+ }
+
+ private void printTextList(PrintStream out, int what, ArrayList textList)
+ {
+ if (textList == null)
+ return;
+ Iterator i = textList.iterator();
+ boolean first = true;
+ while (i.hasNext())
+ {
+ Text item = (Text) i.next();
+ if (item.type == what)
+ {
+ if (first)
+ {
+ out.println();
+ first = false;
+ }
+ if (what == Text.FRIEND)
+ out.print(" friend ");
+ out.println(item.text);
+ }
+ }
+ }
+
+ public void print(CniPrintStream out)
+ {
+ out.print("::" + name.replaceAll("/", "::"));
+ }
+
+ // This prints the body of a class to a CxxPrintStream.
+ private void printContents(CniPrintStream out, ArrayList textList)
+ throws IOException
+ {
+ printTextList(out, Text.PREPEND, textList);
+ out.println();
+
+ out.print("class ");
+ // Don't use our print() -- we don't want the leading "::".
+ out.print(name.replaceAll("/", "::"));
+ if (superClass != null)
+ {
+ out.print(" : public ");
+ superClass.print(out);
+ }
+ out.println();
+ out.println("{");
+
+ printTextList(out, Text.ADD, textList);
+ out.println();
+
+ // Note: methods must come first, as we build the list
+ // of method names while printing them.
+ printMethods(out);
+ printFields(out);
+
+ out.setModifiers(Modifier.PUBLIC);
+ out.println(" static ::java::lang::Class class$;");
+
+ printTextList(out, Text.FRIEND, textList);
+
+ out.print("}");
+ if (Modifier.isInterface(access))
+ out.print(" __attribute__ ((java_interface))");
+ out.println(";");
+
+ printTextList(out, Text.APPEND, textList);
+ }
+
+ public void printFully(PrintStream out) throws IOException
+ {
+ linkSupers();
+
+ ArrayList textList = classpath.getClassTextList(name);
+
+ out.println("// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*-");
+ out.println();
+ String xname = "__" + name.replaceAll("/", "_") + "__";
+ out.println("#ifndef " + xname);
+ out.println("#define " + xname);
+ out.println();
+ out.println("#pragma interface");
+ out.println();
+
+ if (superClass != null)
+ {
+ out.print("#include <");
+ out.print(superName);
+ out.println(".h>");
+ }
+
+ // Write the body of the stream here. This lets
+ // us emit the namespaces without a second pass.
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ CniPrintStream cxxOut = new CniPrintStream(bytes);
+ cxxOut.addClass(this);
+ printContents(cxxOut, textList);
+ cxxOut.printNamespaces(out);
+ bytes.writeTo(out);
+
+ out.println();
+ out.println("#endif // " + xname);
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/CniIncludePrinter.java b/tools/gnu/classpath/tools/javah/CniIncludePrinter.java
new file mode 100644
index 000000000..6561169bb
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/CniIncludePrinter.java
@@ -0,0 +1,69 @@
+/* CniIncludePrinter.java - generate CNI header files
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class CniIncludePrinter
+ extends Printer
+{
+
+ protected CniIncludePrinter(Main classpath)
+ {
+ super(classpath);
+ }
+
+ public void printClass(File outputDir, ClassWrapper klass) throws IOException
+ {
+ // Never write Object or Class. This is a hack, maybe
+ // the user would like to see what they look like...
+ if (klass.name.equals("java/lang/Object")
+ || klass.name.equals("java/lang/Class"))
+ return;
+ File klassFile = new File(outputDir, klass.name + ".h");
+ klassFile.getParentFile().mkdirs();
+ PrintStream ps = new PrintStream(new FileOutputStream(klassFile));
+ klass.printFully(ps);
+ ps.close();
+ }
+
+}
diff --git a/tools/gnu/classpath/tools/javah/CniPrintStream.java b/tools/gnu/classpath/tools/javah/CniPrintStream.java
new file mode 100644
index 000000000..574d7fd5f
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/CniPrintStream.java
@@ -0,0 +1,243 @@
+/* CniPrintStream.java - PrintStream that emits CNI declarations
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.HashSet;
+
+import org.objectweb.asm.Type;
+
+public class CniPrintStream
+ extends PrintStream
+{
+ int currentModifiers = Modifier.PRIVATE;
+
+ // True if we saw an array type.
+ boolean sawArray;
+
+ // All the classes referenced by this header.
+ HashSet allClasses = new HashSet();
+
+ String[] previousPackage = new String[0];
+
+ public CniPrintStream(OutputStream out)
+ {
+ super(out);
+ }
+
+ public void addClass(ClassWrapper cw)
+ {
+ allClasses.add(cw.name);
+ }
+
+ public void setModifiers(int newMods)
+ {
+ newMods &= (Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE);
+ if (newMods != currentModifiers)
+ {
+ switch (newMods)
+ {
+ case Modifier.PUBLIC:
+ println("public:");
+ break;
+ case Modifier.PROTECTED:
+ println("public: // actually protected");
+ break;
+ case Modifier.PRIVATE:
+ println("private:");
+ break;
+ default:
+ println("public: // actually package-private");
+ break;
+ }
+ currentModifiers = newMods;
+ }
+ }
+
+ private String getName(Type type)
+ {
+ if (type == Type.BOOLEAN_TYPE)
+ return "jboolean";
+ else if (type == Type.BYTE_TYPE)
+ return "jbyte";
+ else if (type == Type.CHAR_TYPE)
+ return "jchar";
+ else if (type == Type.SHORT_TYPE)
+ return "jshort";
+ else if (type == Type.INT_TYPE)
+ return "jint";
+ else if (type == Type.LONG_TYPE)
+ return "jlong";
+ else if (type == Type.FLOAT_TYPE)
+ return "jfloat";
+ else if (type == Type.DOUBLE_TYPE)
+ return "jdouble";
+ else
+ {
+ assert type == Type.VOID_TYPE;
+ return "void";
+ }
+ }
+
+ public String getClassName(Type type)
+ {
+ String name = type.toString();
+ name = name.substring(1, name.length() - 1);
+ // Add the plain class name; we'll handle it when
+ // we process namespaces.
+ allClasses.add(name);
+ return "::" + name.replaceAll("/", "::") + " *";
+ }
+
+ public void print(Type type)
+ {
+ int arrayCount = 0;
+ if (type.getSort() == Type.ARRAY)
+ {
+ arrayCount = type.getDimensions();
+ for (int i = 0; i < arrayCount; ++i)
+ print("JArray< ");
+ type = type.getElementType();
+ sawArray = true;
+ }
+ if (type.getSort() == Type.OBJECT)
+ {
+ print(getClassName(type));
+ }
+ else
+ {
+ print(getName(type));
+ }
+ if (arrayCount > 0)
+ {
+ while (arrayCount-- > 0)
+ {
+ print(" > *");
+ }
+ }
+ }
+
+ private void indent(PrintStream out, int n)
+ {
+ for (int i = 0; i < n; ++i)
+ {
+ out.print(" ");
+ }
+ }
+
+ private void moveToPackage(PrintStream out, String[] pkgParts)
+ {
+ // Find greatest common part.
+ int commonIndex;
+ for (commonIndex = 0; commonIndex < previousPackage.length; ++commonIndex)
+ {
+ if (commonIndex >= pkgParts.length)
+ break;
+ if (! previousPackage[commonIndex].equals(pkgParts[commonIndex]))
+ break;
+ }
+ // Close old parts after the common part.
+ for (int j = previousPackage.length - 1; j >= commonIndex; --j)
+ {
+ indent(out, j + 1);
+ out.println("}");
+ }
+ // Open new parts.
+ for (int j = commonIndex; j < pkgParts.length; ++j)
+ {
+ indent(out, j + 1);
+ out.print("namespace ");
+ out.println(pkgParts[j]);
+ indent(out, j + 1);
+ out.println("{");
+ }
+ previousPackage = pkgParts;
+ }
+
+ private void writeClass(PrintStream out, String klass)
+ {
+ int index = klass.lastIndexOf('/');
+ String pkg = klass.substring(0, index);
+ String[] pkgParts = pkg.split("/");
+ String className = klass.substring(index + 1);
+ moveToPackage(out, pkgParts);
+ indent(out, pkgParts.length + 2);
+ out.print("class ");
+ out.print(className);
+ out.println(";");
+ }
+
+ public void printNamespaces(PrintStream out)
+ {
+ if (sawArray)
+ {
+ out.println("#include <gcj/array.h>");
+ out.println();
+ }
+
+ String[] classes = (String[]) allClasses.toArray(new String[0]);
+ Arrays.sort(classes);
+
+ boolean first = true;
+ boolean seen = false;
+ for (int i = 0; i < classes.length; ++i)
+ {
+ String klass = classes[i];
+ if (klass.startsWith("java/lang/") || klass.startsWith("java/io/")
+ || klass.startsWith("java/util/"))
+ continue;
+ if (first)
+ {
+ out.println("extern \"Java\"");
+ out.println("{");
+ first = false;
+ seen = true;
+ }
+ writeClass(out, klass);
+ }
+ if (seen)
+ {
+ moveToPackage(out, new String[0]);
+ out.println("}");
+ }
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/CniStubPrinter.java b/tools/gnu/classpath/tools/javah/CniStubPrinter.java
new file mode 100644
index 000000000..9732e2941
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/CniStubPrinter.java
@@ -0,0 +1,119 @@
+/* CniStubPrinter.java - Generate a CNI stub file
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.Iterator;
+
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.MethodNode;
+
+public class CniStubPrinter
+ extends Printer
+{
+
+ protected CniStubPrinter(Main classpath)
+ {
+ super(classpath);
+ }
+
+ private void printDecl(CniPrintStream out, String className, MethodNode method)
+ {
+ out.print(className);
+ out.print("::");
+ out.print(method.name);
+ out.print("(");
+ Type[] argTypes = Type.getArgumentTypes(method.desc);
+ for (int j = 0; j < argTypes.length; ++j)
+ {
+ if (j > 0)
+ out.print(", ");
+ out.print(argTypes[j]);
+ }
+ out.print(")");
+ }
+
+ public void printClass(File outputDir, ClassWrapper klass) throws IOException
+ {
+ if (! klass.hasNativeMethod())
+ return;
+ File klassFile = new File(outputDir, klass.name + ".cc");
+ klassFile.getParentFile().mkdirs();
+ String className = klass.name.replaceAll("/", "::");
+
+ CniPrintStream out = new CniPrintStream(new FileOutputStream(klassFile));
+ out.println("// This file is intended to give you a head start on implementing native");
+ out.println("// methods using CNI.");
+ out.println("// Be aware: running 'gcjh -stubs' once more for this class may");
+ out.println("// overwrite any edits you have made to this file.");
+ out.println();
+
+ out.println("#include <" + klass.name + ".h>");
+ out.println("#include <gcj/cni.h>");
+ out.println("#include <java/lang/UnsupportedOperationException.h>");
+ out.println();
+
+ Iterator i = klass.methods.iterator();
+ boolean first = true;
+ while (i.hasNext())
+ {
+ MethodNode method = (MethodNode) i.next();
+ if (! Modifier.isNative(method.access))
+ continue;
+ if (! first)
+ out.println();
+ first = false;
+ out.print(Type.getReturnType(method.desc));
+ out.println();
+ printDecl(out, className, method);
+ out.println();
+ out.println("{");
+ out.print(" throw new ::java::lang::UnsupportedOperationException(");
+ out.print("JvNewStringLatin1 (\"");
+ printDecl(out, className, method);
+ out.println("\"));");
+ out.println("}");
+ }
+ out.close();
+ }
+
+}
diff --git a/tools/gnu/classpath/tools/javah/FieldHelper.java b/tools/gnu/classpath/tools/javah/FieldHelper.java
new file mode 100644
index 000000000..ecc82e3c1
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/FieldHelper.java
@@ -0,0 +1,97 @@
+/* FieldHelper.java - field helper methods for CNI
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.lang.reflect.Modifier;
+
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.FieldNode;
+
+public class FieldHelper
+{
+ public static boolean print(CniPrintStream out, FieldNode field,
+ ClassWrapper superType, boolean hasMethodName)
+ {
+ out.setModifiers(field.access);
+ out.print(" ");
+ if (Modifier.isStatic(field.access))
+ out.print("static ");
+ if ((field.value instanceof Integer) || (field.value instanceof Long))
+ out.print("const ");
+ out.print(Type.getType(field.desc));
+ out.print(" ");
+ boolean result = false;
+ if (superType != null && ! Modifier.isStatic(field.access))
+ {
+ out.print("__attribute__((aligned(__alignof__( ");
+ superType.print(out);
+ out.print(")))) ");
+ result = true;
+ }
+ out.print(Keywords.getCxxName(field.name));
+ if (hasMethodName)
+ out.print("__");
+ if (Modifier.isStatic(field.access))
+ {
+ if (field.value instanceof Integer)
+ {
+ out.print(" = ");
+ int val = ((Integer) field.value).intValue();
+ if (val == Integer.MIN_VALUE)
+ out.print("-" + Integer.MAX_VALUE + " - 1");
+ else
+ out.print(val);
+ }
+ else if (field.value instanceof Long)
+ {
+ out.print(" = ");
+ long val = ((Long) field.value).longValue();
+ if (val == Long.MIN_VALUE)
+ out.print("-" + Long.MAX_VALUE + "LL - 1");
+ else
+ {
+ out.print(val);
+ out.print("LL");
+ }
+ }
+ }
+ out.println(";");
+ return result;
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/JniHelper.java b/tools/gnu/classpath/tools/javah/JniHelper.java
new file mode 100644
index 000000000..7c508997e
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/JniHelper.java
@@ -0,0 +1,120 @@
+/* JniHelper.java - name mangling and other JNI support
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.IOException;
+
+import org.objectweb.asm.Type;
+
+public class JniHelper
+{
+ public static String getName(Main classpath, Type type) throws IOException
+ {
+ if (type == Type.BOOLEAN_TYPE)
+ return "jboolean";
+ else if (type == Type.BYTE_TYPE)
+ return "jbyte";
+ else if (type == Type.CHAR_TYPE)
+ return "jchar";
+ else if (type == Type.SHORT_TYPE)
+ return "jshort";
+ else if (type == Type.INT_TYPE)
+ return "jint";
+ else if (type == Type.LONG_TYPE)
+ return "jlong";
+ else if (type == Type.FLOAT_TYPE)
+ return "jfloat";
+ else if (type == Type.DOUBLE_TYPE)
+ return "jdouble";
+ else if (type == Type.VOID_TYPE)
+ return "void";
+
+ if (type.getSort() == Type.ARRAY)
+ {
+ Type elt = type.getElementType();
+ int eltSort = elt.getSort();
+ if (type.getDimensions() == 1 && eltSort != Type.OBJECT)
+ return getName(classpath, elt) + "Array";
+ return "jobjectArray";
+ }
+
+ // assert type.getSort() == Type.OBJECT;
+ String className = type.getClassName();
+ // FIXME: is this correct?
+ if (className.equals("java/lang/Class")
+ || className.equals("java.lang.Class"))
+ return "jclass";
+ if (className.equals("java/lang/String")
+ || className.equals("java.lang.String"))
+ return "jstring";
+
+ ClassWrapper klass = classpath.getClass(className);
+ if (klass.isThrowable())
+ return "jthrowable";
+ return "jobject";
+ }
+
+ public static String mangle(String name)
+ {
+ StringBuffer result = new StringBuffer();
+ for (int i = 0; i < name.length(); ++i)
+ {
+ char c = name.charAt(i);
+ if (c == '_')
+ result.append("_1");
+ else if (c == ';')
+ result.append("_2");
+ else if (c == '[')
+ result.append("_3");
+ else if (c == '/')
+ result.append("_");
+ else if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z'))
+ result.append(c);
+ else
+ {
+ result.append("_0");
+ // Sigh.
+ String hex = "0000" + Integer.toHexString(c);
+ result.append(hex.substring(hex.length() - 4));
+ }
+ }
+ return result.toString();
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/JniIncludePrinter.java b/tools/gnu/classpath/tools/javah/JniIncludePrinter.java
new file mode 100644
index 000000000..c01634007
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/JniIncludePrinter.java
@@ -0,0 +1,151 @@
+/* JniIncludePrinter.java - Generate a JNI header file
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.Iterator;
+
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.FieldNode;
+import org.objectweb.asm.tree.MethodNode;
+
+public class JniIncludePrinter
+ extends Printer
+{
+
+ protected JniIncludePrinter(Main classpath)
+ {
+ super(classpath);
+ }
+
+ private void writeFields(ClassWrapper klass, JniPrintStream out)
+ {
+ boolean wroteAny = false;
+ for (; klass != null; klass = klass.superClass)
+ {
+ Iterator i = klass.fields.iterator();
+ while (i.hasNext())
+ {
+ FieldNode field = (FieldNode) i.next();
+ if (! Modifier.isStatic(field.access)
+ || ! Modifier.isFinal(field.access))
+ continue;
+ if (! (field.value instanceof Integer)
+ && ! (field.value instanceof Long))
+ continue;
+
+ // Note that we don't want to mangle the field name.
+ String name = (JniHelper.mangle(klass.name) + "_" + field.name);
+ out.print("#undef ");
+ out.println(name);
+ out.print("#define ");
+ out.print(name);
+ out.print(" ");
+ out.print(field.value);
+ if (field.value instanceof Integer)
+ out.print("L");
+ else if (field.value instanceof Long)
+ out.print("LL");
+ out.println();
+ wroteAny = true;
+ }
+ }
+ if (wroteAny)
+ out.println();
+ }
+
+ public void printClass(File outputDir, ClassWrapper klass) throws IOException
+ {
+ if (! klass.hasNativeMethod())
+ return;
+ String xname = JniHelper.mangle(klass.name);
+ File outFile = new File(outputDir, xname + ".h");
+
+ JniPrintStream out = new JniPrintStream(classpath,
+ new FileOutputStream(outFile),
+ klass);
+ out.println("/* DO NOT EDIT THIS FILE - it is machine generated */");
+ out.println();
+ out.print("#ifndef __");
+ out.print(xname);
+ out.println("__");
+ out.print("#define __");
+ out.print(xname);
+ out.println("__");
+ out.println();
+ out.println("#include <jni.h>");
+ out.println();
+ out.println("#ifdef __cplusplus");
+ out.println("extern \"C\"");
+ out.println("{");
+ out.println("#endif");
+ out.println();
+
+ Iterator i = klass.methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode method = (MethodNode) i.next();
+ if (! Modifier.isNative(method.access))
+ continue;
+ out.print("JNIEXPORT ");
+ out.print(Type.getReturnType(method.desc));
+ out.print(" JNICALL ");
+ out.print(method, xname);
+ out.println(";");
+ }
+
+ out.println();
+
+ writeFields(klass, out);
+
+ out.println("#ifdef __cplusplus");
+ out.println("}");
+ out.println("#endif");
+ out.println();
+ out.print("#endif /* __");
+ out.print(xname);
+ out.println("__ */");
+
+ out.close();
+ }
+
+}
diff --git a/tools/gnu/classpath/tools/javah/JniPrintStream.java b/tools/gnu/classpath/tools/javah/JniPrintStream.java
new file mode 100644
index 000000000..a0461f475
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/JniPrintStream.java
@@ -0,0 +1,115 @@
+/* JniPrintStream.java - PrintStream that emits JNI declarations
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.MethodNode;
+
+public class JniPrintStream
+ extends PrintStream
+{
+ Main classpath;
+
+ // This is used to determine whether a method has an overload.
+ HashMap methodNameMap = new HashMap();
+
+ public JniPrintStream(Main classpath, OutputStream out, ClassWrapper klass)
+ {
+ super(out);
+ this.classpath = classpath;
+ computeOverloads(klass);
+ }
+
+ private void computeOverloads(ClassWrapper klass)
+ {
+ Iterator i = klass.methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode method = (MethodNode) i.next();
+ if (! Modifier.isNative(method.access))
+ continue;
+ if (methodNameMap.containsKey(method.name))
+ {
+ Integer val = (Integer) methodNameMap.get(method.name);
+ methodNameMap.put(method.name, new Integer(val.intValue() + 1));
+ }
+ else
+ methodNameMap.put(method.name, new Integer(1));
+ }
+ }
+
+ public void print(Type type) throws IOException
+ {
+ print(JniHelper.getName(classpath, type));
+ }
+
+ public void print(MethodNode method, String className) throws IOException
+ {
+ print("Java_");
+ print(className);
+ print("_");
+ print(JniHelper.mangle(method.name));
+ Integer overloadCount = (Integer) methodNameMap.get(method.name);
+ if (overloadCount.intValue() > 1)
+ {
+ print("__");
+ int lastOffset = method.desc.lastIndexOf(')');
+ print(JniHelper.mangle(method.desc.substring(1, lastOffset)));
+ }
+ print(" (JNIEnv *env");
+ if (Modifier.isStatic(method.access))
+ print(", jclass");
+ else
+ print(", jobject");
+ Type[] types = Type.getArgumentTypes(method.desc);
+ for (int i = 0; i < types.length; ++i)
+ {
+ print(", ");
+ print(types[i]);
+ }
+ print(")");
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/JniStubPrinter.java b/tools/gnu/classpath/tools/javah/JniStubPrinter.java
new file mode 100644
index 000000000..d590a5cd1
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/JniStubPrinter.java
@@ -0,0 +1,98 @@
+/* JniStubPrinter.java - Generate JNI stub files
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.util.Iterator;
+
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.MethodNode;
+
+public class JniStubPrinter
+ extends Printer
+{
+
+ protected JniStubPrinter(Main classpath)
+ {
+ super(classpath);
+ }
+
+ public void printClass(File outputDir, ClassWrapper klass) throws IOException
+ {
+ if (! klass.hasNativeMethod())
+ return;
+ String xname = JniHelper.mangle(klass.name);
+ File outFile = new File(outputDir, xname + ".c");
+
+ JniPrintStream out = new JniPrintStream(classpath,
+ new FileOutputStream(outFile),
+ klass);
+ out.println("/* This file is intended to give you a head start on implementing native");
+ out.println(" methods using CNI.");
+ out.println(" Be aware: running 'gcjh -stubs' once more for this class may");
+ out.println(" overwrite any edits you have made to this file. */");
+ out.println();
+ out.print("#include <");
+ out.print(xname);
+ out.println(".h>");
+
+ Iterator i = klass.methods.iterator();
+ while (i.hasNext())
+ {
+ MethodNode method = (MethodNode) i.next();
+ if (! Modifier.isNative(method.access))
+ continue;
+ out.println();
+ out.print(Type.getReturnType(method.desc));
+ out.println();
+ out.print(method, xname);
+ out.println();
+ out.println("{");
+ out.print(" (*env)->FatalError (env, \"");
+ out.print(method, xname);
+ out.println(" not implemented\");");
+ out.println("}");
+ }
+ out.close();
+ }
+
+}
diff --git a/tools/gnu/classpath/tools/javah/Keywords.java b/tools/gnu/classpath/tools/javah/Keywords.java
new file mode 100644
index 000000000..46543ba45
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/Keywords.java
@@ -0,0 +1,85 @@
+/* Keywords.java - List of C++ keywords
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.util.HashSet;
+
+public class Keywords
+{
+ private static final String[] words = { "and", "and_eq", "asm", "auto",
+ "bitand", "bitor", "bool", "break",
+ "case", "catch", "char", "class",
+ "compl", "const", "const_cast",
+ "continue", "default", "delete", "do",
+ "double", "dynamic_cast", "else",
+ "enum", "explicit", "export",
+ "extern", "false", "float", "for",
+ "friend", "goto", "if", "inline",
+ "int", "long", "mutable", "namespace",
+ "new", "not", "not_eq", "operator",
+ "or", "or_eq", "private", "protected",
+ "public", "register",
+ "reinterpret_cast", "return", "short",
+ "signed", "sizeof", "static",
+ "static_cast", "struct", "switch",
+ "template", "this", "throw", "true",
+ "try", "typedef", "typeid",
+ "typename", "typeof", "union",
+ "unsigned", "using", "virtual",
+ "void", "volatile", "wchar_t",
+ "while", "xor", "xor_eq" };
+
+ private static final HashSet keywords;
+ static
+ {
+ keywords = new HashSet();
+ for (int i = 0; i < words.length; ++i)
+ keywords.add(words[i]);
+ }
+
+ public static String getCxxName(String name)
+ {
+ int i;
+ for (i = name.length() - 1; i >= 0 && name.charAt(i) == '$'; --i)
+ ;
+ if (keywords.contains(name.substring(0, i + 1)))
+ return name + "$";
+ return name;
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/Main.java b/tools/gnu/classpath/tools/javah/Main.java
new file mode 100644
index 000000000..f342d4ae1
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/Main.java
@@ -0,0 +1,375 @@
+/* Main.java - javah main program
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import gnu.classpath.tools.getopt.ClasspathToolParser;
+import gnu.classpath.tools.getopt.Option;
+import gnu.classpath.tools.getopt.OptionException;
+import gnu.classpath.tools.getopt.Parser;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.objectweb.asm.ClassReader;
+
+public class Main
+{
+ // This is an option group for classpath-related options,
+ // and also is used for loading classes.
+ PathOptionGroup classpath = new PathOptionGroup();
+
+ // The output directory.
+ String outputDir;
+
+ // The loader that we use to load class files.
+ URLClassLoader loader;
+
+ // In -all mode, the name of the directory to scan.
+ String allDirectory;
+
+ // True for verbose mode.
+ boolean verbose;
+
+ // True if we're emitting stubs.
+ boolean stubs;
+
+ // True if we're emitting CNI code.
+ boolean cni;
+
+ // Map class names to class wrappers.
+ HashMap classMap = new HashMap();
+
+ // Map class names to lists of Text objects.
+ HashMap textMap = new HashMap();
+
+ void readCommandFile(String textFileName) throws OptionException
+ {
+ FileInputStream fis;
+ try
+ {
+ fis = new FileInputStream(textFileName);
+ }
+ catch (FileNotFoundException ignore)
+ {
+ throw new OptionException("file \"" + textFileName + "\" not found");
+ }
+ BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
+ String currentClass = null;
+ ArrayList currentValues = null;
+ while (true)
+ {
+ String line;
+ try
+ {
+ line = reader.readLine();
+ }
+ catch (IOException _)
+ {
+ break;
+ }
+ if (line == null)
+ break;
+ line = line.trim();
+ if (line.length() == 0 || line.charAt(0) == '#')
+ continue;
+ int index = line.indexOf(' ');
+ String cmd = line.substring(0, index);
+ String value = line.substring(index + 1);
+ int cmdValue;
+ if ("class".equals(cmd))
+ {
+ if (currentClass != null)
+ {
+ textMap.put(currentClass, currentValues);
+ }
+ currentClass = value;
+ currentValues = new ArrayList();
+ continue;
+ }
+ if (currentClass == null)
+ throw new OptionException("no class set");
+ if ("add".equals(cmd))
+ cmdValue = Text.ADD;
+ else if ("append".equals(cmd))
+ cmdValue = Text.APPEND;
+ else if ("prepend".equals(cmd))
+ cmdValue = Text.PREPEND;
+ else if ("friend".equals(cmd))
+ cmdValue = Text.FRIEND;
+ else
+ throw new OptionException("unrecognized command: " + cmd);
+ currentValues.add(new Text(cmdValue, value));
+ }
+ if (currentClass != null)
+ {
+ textMap.put(currentClass, currentValues);
+ }
+ }
+
+ void scanDirectory(File dir, final HashSet results)
+ {
+ File[] files = dir.listFiles(new FileFilter()
+ {
+ public boolean accept(File pathname)
+ {
+ if (pathname.isDirectory())
+ {
+ scanDirectory(pathname, results);
+ return false;
+ }
+ return pathname.getName().endsWith(".class");
+ }
+ });
+ if (files != null)
+ results.addAll(Arrays.asList(files));
+ }
+
+ private Parser getParser()
+ {
+ ClasspathToolParser result = new ClasspathToolParser("javah", true);
+ result.setHeader("usage: javah [OPTIONS] CLASS...");
+ result.add(classpath);
+ result.add(new Option('d', "Set output directory", "DIR")
+ {
+ public void parsed(String dir) throws OptionException
+ {
+ if (outputDir != null)
+ throw new OptionException("-d already seen");
+ outputDir = dir;
+ }
+ });
+ result.add(new Option("cmdfile", "Read command file", "FILE")
+ {
+ public void parsed(String file) throws OptionException
+ {
+ readCommandFile(file);
+ }
+ });
+ result.add(new Option("all", "Operate on all class files under directory",
+ "DIR")
+ {
+ public void parsed(String arg) throws OptionException
+ {
+ // FIXME: lame restriction...
+ if (allDirectory != null)
+ throw new OptionException("-all already specified");
+ allDirectory = arg;
+ }
+ });
+ result.add(new Option("stubs", "Emit stub implementation")
+ {
+ public void parsed(String arg0) throws OptionException
+ {
+ stubs = true;
+ }
+ });
+ result.add(new Option("cni", "Emit CNI stubs or header (default JNI)")
+ {
+ public void parsed(String arg0) throws OptionException
+ {
+ cni = true;
+ }
+ });
+ result.add(new Option("verbose", "Set verbose mode")
+ {
+ public void parsed(String arg0) throws OptionException
+ {
+ verbose = true;
+ }
+ });
+ return result;
+ }
+
+ private File makeOutputDirectory() throws IOException
+ {
+ File outputFile;
+ if (outputDir == null)
+ outputFile = new File(".");
+ else
+ {
+ outputFile = new File(outputDir);
+ outputFile.mkdirs();
+ }
+ return outputFile;
+ }
+
+ private void writeHeaders(ArrayList klasses, Printer printer,
+ File outputDirFile) throws IOException
+ {
+ Iterator i = klasses.iterator();
+ while (i.hasNext())
+ {
+ ClassWrapper klass = (ClassWrapper) i.next();
+ if (verbose)
+ System.err.println("[writing " + klass + "]");
+ printer.printClass(outputDirFile, klass);
+ }
+ }
+
+ private void run(String[] args) throws IOException
+ {
+ Parser p = getParser();
+ String[] classNames = p.parse(args);
+ loader = classpath.getLoader();
+
+ File outputFile = makeOutputDirectory();
+ Printer printer;
+ if (! cni)
+ {
+ if (stubs)
+ printer = new JniStubPrinter(this);
+ else
+ printer = new JniIncludePrinter(this);
+ }
+ else
+ {
+ if (stubs)
+ printer = new CniStubPrinter(this);
+ else
+ printer = new CniIncludePrinter(this);
+ }
+
+ // First we load all of the files. That way if
+ // there are references between the files we will
+ // be loading the set that the user asked for.
+ HashSet klasses = new HashSet();
+ if (allDirectory != null)
+ scanDirectory(new File(allDirectory), klasses);
+ // Add the command-line arguments. We use the type of
+ // an item in 'klasses' to decide how to load each class.
+ for (int i = 0; i < classNames.length; ++i)
+ {
+ if (classNames[i].endsWith(".class"))
+ {
+ klasses.add(new File(classNames[i]));
+ }
+ else
+ {
+ klasses.add(classNames[i]);
+ }
+ }
+
+ Iterator i = klasses.iterator();
+ ArrayList results = new ArrayList();
+ while (i.hasNext())
+ {
+ // Let user specify either kind of class name or a
+ // file name.
+ Object item = i.next();
+ ClassWrapper klass;
+ if (item instanceof File)
+ {
+ // Load class from file.
+ if (verbose)
+ System.err.println("[reading file " + item + "]");
+ klass = getClass((File) item);
+ }
+ else
+ {
+ // Load class given the class name.
+ String className = ((String) item).replace('.', '/');
+ if (verbose)
+ System.err.println("[reading class " + className + "]");
+ klass = getClass(className);
+ }
+ results.add(klass);
+ }
+
+ writeHeaders(results, printer, outputFile);
+ }
+
+ public ArrayList getClassTextList(String name)
+ {
+ return (ArrayList) textMap.get(name);
+ }
+
+ private ClassWrapper readClass(InputStream is) throws IOException
+ {
+ ClassReader r = new ClassReader(is);
+ ClassWrapper result = new ClassWrapper(this);
+ r.accept(result, true);
+ is.close();
+ return result;
+ }
+
+ private ClassWrapper getClass(File fileName) throws IOException
+ {
+ InputStream is = new FileInputStream(fileName);
+ ClassWrapper result = readClass(is);
+ if (classMap.containsKey(result.name))
+ throw new IllegalArgumentException("class " + result.name
+ + " already loaded");
+ classMap.put(result.name, result);
+ return result;
+ }
+
+ public ClassWrapper getClass(String name) throws IOException
+ {
+ if (! classMap.containsKey(name))
+ {
+ String resource = name.replace('.', '/') + ".class";
+ URL url = loader.findResource(resource);
+ if (url == null)
+ throw new IOException("can't find class file " + resource);
+ InputStream is = url.openStream();
+ ClassWrapper result = readClass(is);
+ classMap.put(name, result);
+ }
+ return (ClassWrapper) classMap.get(name);
+ }
+
+ public static void main(String[] args) throws IOException
+ {
+ Main m = new Main();
+ m.run(args);
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/MethodHelper.java b/tools/gnu/classpath/tools/javah/MethodHelper.java
new file mode 100644
index 000000000..6657f115a
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/MethodHelper.java
@@ -0,0 +1,130 @@
+/* MethodHelper.java - helper class for manipulating methods
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.lang.reflect.Modifier;
+import java.util.Iterator;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+
+public class MethodHelper
+{
+
+ public static boolean overrides(MethodNode derived, MethodNode base)
+ {
+ if (! derived.name.equals(base.name))
+ return false;
+ if (! derived.desc.equals(base.desc))
+ return false;
+ // FIXME: permission madness?
+ return true;
+ }
+
+ public static String getBridgeTarget(MethodNode meth)
+ {
+ if ((meth.access & Opcodes.ACC_BRIDGE) == 0)
+ return null;
+ Iterator i = meth.instructions.iterator();
+ while (i.hasNext())
+ {
+ AbstractInsnNode insn = (AbstractInsnNode) i.next();
+ if (! (insn instanceof MethodInsnNode))
+ continue;
+ return ((MethodInsnNode) insn).desc;
+ }
+ return null;
+ }
+
+ public static void print(CniPrintStream out, MethodNode meth,
+ ClassWrapper declarer, boolean isBridgeTarget)
+ {
+ if ("<clinit>".equals(meth.name))
+ return;
+ boolean isInit = "<init>".equals(meth.name);
+ out.setModifiers(meth.access);
+ out.print(" ");
+ if (Modifier.isStatic(meth.access))
+ out.print("static ");
+ // If a class is final then we might as well skip 'virtual'.
+ // The reason here is that it is safe in this case for C++
+ // ABI code to generate a direct call. The method does end
+ // up in the vtable (for BC code) but we don't care. Also,
+ // the class can't be derived from anyway.
+ else if (! isInit && ! Modifier.isPrivate(meth.access)
+ && ! Modifier.isFinal(declarer.access))
+ out.print("virtual ");
+ if (! isInit)
+ {
+ out.print(Type.getReturnType(meth.desc));
+ out.print(" ");
+ if (isBridgeTarget)
+ {
+ out.print("target$");
+ out.print(meth.name);
+ }
+ else
+ {
+ out.print(Keywords.getCxxName(meth.name));
+ }
+ }
+ else
+ {
+ String name = declarer.name;
+ int index = name.lastIndexOf('/');
+ name = name.substring(index + 1);
+ out.print(name);
+ }
+ out.print("(");
+ Type[] argTypes = Type.getArgumentTypes(meth.desc);
+ for (int i = 0; i < argTypes.length; ++i)
+ {
+ if (i > 0)
+ out.print(", ");
+ out.print(argTypes[i]);
+ }
+ out.print(")");
+ if (Modifier.isAbstract(meth.access))
+ out.print(" = 0");
+ out.println(";");
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/PackageWrapper.java b/tools/gnu/classpath/tools/javah/PackageWrapper.java
new file mode 100644
index 000000000..11b38b20f
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/PackageWrapper.java
@@ -0,0 +1,54 @@
+/* PackageWrapper.java - represent a package
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+public class PackageWrapper
+{
+ // This is null if there is no parent package.
+ PackageWrapper parent;
+
+ // Name of this package relative to its parent's name.
+ String name;
+
+ public PackageWrapper(PackageWrapper parent, String name)
+ {
+ this.parent = parent;
+ this.name = name;
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/PathOptionGroup.java b/tools/gnu/classpath/tools/javah/PathOptionGroup.java
new file mode 100644
index 000000000..f11077fa0
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/PathOptionGroup.java
@@ -0,0 +1,135 @@
+/* PathOptionGroup.java - handle classpath-setting options
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import gnu.classpath.tools.getopt.Option;
+import gnu.classpath.tools.getopt.OptionException;
+import gnu.classpath.tools.getopt.OptionGroup;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+public class PathOptionGroup
+ extends OptionGroup
+{
+ ArrayList classpath = new ArrayList();
+
+ ArrayList bootclasspath = new ArrayList();
+
+ void setPath(ArrayList list, String path)
+ {
+ list.clear();
+ StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
+ while (st.hasMoreTokens())
+ {
+ list.add(st.nextToken());
+ }
+ }
+
+ void addExtDirs(ArrayList list, String path)
+ {
+ StringTokenizer tok = new StringTokenizer(path, File.pathSeparator);
+ while (tok.hasMoreTokens())
+ {
+ File dir = new File(tok.nextToken());
+ list.addAll(Arrays.asList(dir.list(new FilenameFilter()
+ {
+ public boolean accept(File dir, String name)
+ {
+ return name.endsWith(".zip") || name.endsWith(".jar");
+ }
+ })));
+ }
+ }
+
+ public PathOptionGroup()
+ {
+ super("Class path options");
+
+ add(new Option("classpath", "Set the class path", "PATH")
+ {
+ public void parsed(String path) throws OptionException
+ {
+ setPath(classpath, path);
+ }
+ });
+ add(new Option('I', "Add directory to class path", "DIR")
+ {
+ public void parsed(String path) throws OptionException
+ {
+ classpath.add(path);
+ }
+ });
+ add(new Option("bootclasspath", "Set the boot class path", "PATH")
+ {
+ public void parsed(String path) throws OptionException
+ {
+ setPath(bootclasspath, path);
+ }
+ });
+ add(new Option("extdirs", "Set the extension directory path", "PATH")
+ {
+ public void parsed(String path) throws OptionException
+ {
+ addExtDirs(classpath, path);
+ }
+ });
+ }
+
+ public URLClassLoader getLoader() throws MalformedURLException
+ {
+ ArrayList urls = new ArrayList();
+ classpath.addAll(bootclasspath);
+ Iterator i = classpath.iterator();
+ while (i.hasNext())
+ {
+ String f = (String) i.next();
+ urls.add(new File(f).toURL());
+ }
+ URL[] urlArray = (URL[]) urls.toArray(new URL[0]);
+ return new URLClassLoader(urlArray);
+ }
+}
diff --git a/tools/gnu/classpath/tools/javah/Printer.java b/tools/gnu/classpath/tools/javah/Printer.java
new file mode 100644
index 000000000..0c25934e2
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/Printer.java
@@ -0,0 +1,55 @@
+/* Print.java - abstract base class for printing classes
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+import java.io.File;
+import java.io.IOException;
+
+public abstract class Printer
+{
+ protected Main classpath;
+
+ protected Printer(Main classpath)
+ {
+ this.classpath = classpath;
+ }
+
+ public abstract void printClass(File outputDir, ClassWrapper klass)
+ throws IOException;
+}
diff --git a/tools/gnu/classpath/tools/javah/Text.java b/tools/gnu/classpath/tools/javah/Text.java
new file mode 100644
index 000000000..37a1ad669
--- /dev/null
+++ b/tools/gnu/classpath/tools/javah/Text.java
@@ -0,0 +1,60 @@
+/* Text.java - convenience class for CNI header text insertions
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+
+package gnu.classpath.tools.javah;
+
+public class Text
+{
+ public static final int ADD = 0;
+
+ public static final int APPEND = 1;
+
+ public static final int FRIEND = 2;
+
+ public static final int PREPEND = 3;
+
+ public int type;
+
+ public String text;
+
+ public Text(int type, String text)
+ {
+ this.type = type;
+ this.text = text;
+ }
+}
diff --git a/tools/gnu/classpath/tools/keytool/Command.java b/tools/gnu/classpath/tools/keytool/Command.java
index da9293116..af91e4a71 100644
--- a/tools/gnu/classpath/tools/keytool/Command.java
+++ b/tools/gnu/classpath/tools/keytool/Command.java
@@ -56,7 +56,6 @@ import gnu.java.security.hash.MD5;
import gnu.java.security.hash.Sha160;
import gnu.java.security.util.Util;
import gnu.java.security.x509.X500DistinguishedName;
-import gnu.javax.security.auth.callback.ConsoleCallbackHandler;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -374,6 +373,11 @@ abstract class Command
/**
* Convenience method to setup the key store given its type, its password, its
* location and portentially a specialized security provider.
+ * <p>
+ * Calls the method with the same name and 5 arguments passing
+ * <code>false</code> to the first argument implying that no attempt to
+ * create the keystore will be made if one was not found at the designated
+ * location.
*
* @param className the potentially null fully qualified class name of a
* security provider to add at runtime, if no installed provider is
@@ -388,10 +392,31 @@ abstract class Command
throws IOException, UnsupportedCallbackException, KeyStoreException,
NoSuchAlgorithmException, CertificateException
{
+ setKeyStoreParams(false, className, type, password, url);
+ }
+
+ /**
+ * Convenience method to setup the key store given its type, its password, its
+ * location and portentially a specialized security provider.
+ *
+ * @param createIfNotFound if <code>true</code> then create the keystore if
+ * it was not found; otherwise do not.
+ * @param className the potentially null fully qualified class name of a
+ * security provider to add at runtime, if no installed provider is
+ * able to provide a key store implementation of the desired type.
+ * @param type the potentially null type of the key store to request from the
+ * key store factory.
+ * @param password the potentially null password protecting the key store.
+ * @param url the URL of the key store.
+ */
+ protected void setKeyStoreParams(boolean createIfNotFound, String className,
+ String type, String password, String url)
+ throws IOException, UnsupportedCallbackException, KeyStoreException,
+ NoSuchAlgorithmException, CertificateException
+ {
setProviderClassNameParam(className);
setKeystoreTypeParam(type);
- setKeystorePasswordParam(password);
- setKeystoreURLParam(url);
+ setKeystoreURLParam(createIfNotFound, url, password);
}
/**
@@ -402,7 +427,7 @@ abstract class Command
* security provider to add, if it is not already installed, to the
* set of available providers.
*/
- protected void setProviderClassNameParam(String className)
+ private void setProviderClassNameParam(String className)
{
if (Configuration.DEBUG)
log.fine("setProviderClassNameParam(" + className + ")"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -430,7 +455,7 @@ abstract class Command
* For GNU Classpath this is <i>gkr</i> which stands for the "Gnu
* KeyRing" specifications.
*/
- protected void setKeystoreTypeParam(String type)
+ private void setKeystoreTypeParam(String type)
{
if (Configuration.DEBUG)
log.fine("setKeystoreTypeParam(" + type + ")"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -491,7 +516,7 @@ abstract class Command
* @throws SecurityException if no password is available, even after prompting
* the user.
*/
- protected void setKeyPasswordParam() throws IOException,
+ private void setKeyPasswordParam() throws IOException,
UnsupportedCallbackException
{
String prompt = Messages.getFormattedString("Command.21", alias); //$NON-NLS-1$
@@ -503,7 +528,7 @@ abstract class Command
throw new SecurityException(Messages.getString("Command.23")); //$NON-NLS-1$
}
- protected void setKeystorePasswordParam(String password) throws IOException,
+ private void setKeystorePasswordParam(String password) throws IOException,
UnsupportedCallbackException
{
if (password != null)
@@ -521,14 +546,20 @@ abstract class Command
/**
* Set the key store URL to use.
*
- * @param url
+ * @param createIfNotFound when <code>true</code> an attempt to create a
+ * keystore at the designated location will be made. If
+ * <code>false</code> then no file creation is carried out, which
+ * may cause an exception to be thrown later.
+ * @param url the full, or partial, URL to the keystore location.
+ * @param password an eventually null string to use when loading the keystore.
* @throws IOException
* @throws KeyStoreException
* @throws UnsupportedCallbackException
* @throws NoSuchAlgorithmException
* @throws CertificateException
*/
- protected void setKeystoreURLParam(String url) throws IOException,
+ private void setKeystoreURLParam(boolean createIfNotFound, String url,
+ String password) throws IOException,
KeyStoreException, UnsupportedCallbackException, NoSuchAlgorithmException,
CertificateException
{
@@ -541,16 +572,19 @@ abstract class Command
throw new InvalidParameterException(Messages.getString("Command.36")); //$NON-NLS-1$
url = userHome.trim() + "/.keystore"; //$NON-NLS-1$
- // if it does not exist create it
- new File(url).createNewFile();
+ // if it does not exist create it if required
+ if (createIfNotFound)
+ new File(url).createNewFile();
url = "file:" + url; //$NON-NLS-1$
}
else
{
url = url.trim();
if (url.indexOf(":") == -1) // if it does not exist create it //$NON-NLS-1$
- new File(url).createNewFile();
-
+ {
+ if (createIfNotFound)
+ new File(url).createNewFile();
+ }
url = "file:" + url; //$NON-NLS-1$
}
@@ -590,6 +624,8 @@ abstract class Command
store = KeyStore.getInstance(storeType, provider);
}
+ setKeystorePasswordParam(password);
+
// now we have a KeyStore instance. load it
// KeyStore public API claims: "...In order to create an empty keystore,
// you pass null as the InputStream argument to the load method.
@@ -1166,7 +1202,8 @@ abstract class Command
* <p>
* If no installed providers were found, this method falls back on the GNU
* provider, by-passing the Security search mechanism. The default console
- * callback handler implementation is {@link ConsoleCallbackHandler}.
+ * callback handler implementation is
+ * {@link gnu.javax.security.auth.callback.ConsoleCallbackHandler}.
*
* @return a console-based {@link CallbackHandler}.
*/
diff --git a/tools/gnu/classpath/tools/keytool/GenKeyCmd.java b/tools/gnu/classpath/tools/keytool/GenKeyCmd.java
index e9034eac2..e2048b223 100644
--- a/tools/gnu/classpath/tools/keytool/GenKeyCmd.java
+++ b/tools/gnu/classpath/tools/keytool/GenKeyCmd.java
@@ -217,7 +217,6 @@ class GenKeyCmd extends Command
protected String _providerClassName;
private int keySize;
private X500DistinguishedName distinguishedName;
- private Parser cmdOptionsParser;
// default 0-arguments constructor
@@ -303,7 +302,7 @@ class GenKeyCmd extends Command
void setup() throws Exception
{
- setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
+ setKeyStoreParams(true, _providerClassName, _ksType, _ksPassword, _ksURL);
setAliasParam(_alias);
setKeyPasswordParam(_password);
setAlgorithmParams(_keyAlgorithm, _sigAlgorithm);
diff --git a/tools/gnu/classpath/tools/keytool/IdentityDBCmd.java b/tools/gnu/classpath/tools/keytool/IdentityDBCmd.java
index 94234c5b9..d0de589d9 100644
--- a/tools/gnu/classpath/tools/keytool/IdentityDBCmd.java
+++ b/tools/gnu/classpath/tools/keytool/IdentityDBCmd.java
@@ -149,7 +149,7 @@ class IdentityDBCmd extends Command
void setup() throws Exception
{
setInputStreamParam(_idbFileName);
- setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
+ setKeyStoreParams(true, _providerClassName, _ksType, _ksPassword, _ksURL);
if (Configuration.DEBUG)
{
log.fine("-identitydb handler will use the following options:"); //$NON-NLS-1$
diff --git a/tools/gnu/classpath/tools/keytool/ImportCmd.java b/tools/gnu/classpath/tools/keytool/ImportCmd.java
index e733ad4c1..1eaf6b337 100644
--- a/tools/gnu/classpath/tools/keytool/ImportCmd.java
+++ b/tools/gnu/classpath/tools/keytool/ImportCmd.java
@@ -207,7 +207,6 @@ class ImportCmd extends Command
protected String _ksPassword;
protected String _providerClassName;
private CertificateFactory x509Factory;
- private boolean imported;
/**
* Pathname to a GKR-type cacerts file to use when trustCACerts is true. This
* is usually a file named "cacerts.gkr" located in lib/security in the folder
@@ -292,7 +291,7 @@ class ImportCmd extends Command
void setup() throws Exception
{
setInputStreamParam(_certFileName);
- setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
+ setKeyStoreParams(true, _providerClassName, _ksType, _ksPassword, _ksURL);
setAliasParam(_alias);
setKeyPasswordNoPrompt(_password);
if (Configuration.DEBUG)
diff --git a/tools/gnu/classpath/tools/keytool/Main.java b/tools/gnu/classpath/tools/keytool/Main.java
index 08d55556e..7c3ebd053 100644
--- a/tools/gnu/classpath/tools/keytool/Main.java
+++ b/tools/gnu/classpath/tools/keytool/Main.java
@@ -296,14 +296,6 @@ public class Main
log.exiting(this.getClass().getName(), "teardown"); //$NON-NLS-1$
}
- private void printHelp()
- {
- if (helpPrinted)
- return;
-
- helpPrinted = true;
- }
-
// Inner class(es)
// ==========================================================================
diff --git a/vm/reference/gnu/java/lang/management/VMMemoryMXBeanImpl.java b/vm/reference/gnu/java/lang/management/VMMemoryMXBeanImpl.java
index 193e33535..43b9ae1a1 100644
--- a/vm/reference/gnu/java/lang/management/VMMemoryMXBeanImpl.java
+++ b/vm/reference/gnu/java/lang/management/VMMemoryMXBeanImpl.java
@@ -90,7 +90,7 @@ final class VMMemoryMXBeanImpl
* information when memory is allocated and deallocated. The
* format of the output is left up to the virtual machine.
*
- * @return true if verbose class loading output is on.
+ * @return true if verbose memory usage output is on.
*/
static native boolean isVerbose();
@@ -101,7 +101,7 @@ final class VMMemoryMXBeanImpl
* may be called by multiple threads concurrently, but there
* is only one global setting of verbosity that is affected.
*
- * @param verbose the new setting for verbose class loading
+ * @param verbose the new setting for verbose memory usage
* output.
*/
static native void setVerbose(boolean verbose);
diff --git a/vm/reference/gnu/java/lang/management/VMMemoryPoolMXBeanImpl.java b/vm/reference/gnu/java/lang/management/VMMemoryPoolMXBeanImpl.java
index e32e8f0ac..723d4e897 100644
--- a/vm/reference/gnu/java/lang/management/VMMemoryPoolMXBeanImpl.java
+++ b/vm/reference/gnu/java/lang/management/VMMemoryPoolMXBeanImpl.java
@@ -106,6 +106,15 @@ final class VMMemoryPoolMXBeanImpl
static native MemoryUsage getPeakUsage(String name);
/**
+ * Returns the type of memory used by the specified pool.
+ * The value must be either "HEAP" or "NON_HEAP".
+ *
+ * @param name the name of the pool to obtain statistics on.
+ * @return the type of the given pool.
+ */
+ static native String getType(String name);
+
+ /**
* Returns the current usage level of the specified pool.
* This is only called if the pool is valid.
*
diff --git a/vm/reference/java/lang/VMSystem.java b/vm/reference/java/lang/VMSystem.java
index f96986df3..bf46b27aa 100644
--- a/vm/reference/java/lang/VMSystem.java
+++ b/vm/reference/java/lang/VMSystem.java
@@ -135,7 +135,10 @@ final class VMSystem
* @return the current time
* @see java.util.Date
*/
- public static native long currentTimeMillis();
+ public static long currentTimeMillis()
+ {
+ return nanoTime() / 1000000L;
+ }
/**
* <p>
@@ -162,10 +165,7 @@ final class VMSystem
* @return the time of a system timer in nanoseconds.
* @since 1.5
*/
- public static long nanoTime()
- {
- return currentTimeMillis() * 1000;
- }
+ public static native long nanoTime();
/**
* Returns a list of 'name=value' pairs representing the current environment